Only this pageAll pages
Powered by GitBook
1 of 57

Pharos Docs

Introduction

Loading...

Loading...

Loading...

Loading...

Loading...

Architecture

Loading...

Loading...

Loading...

Core Technologies

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Network Overview

Loading...

Loading...

Loading...

Loading...

Node & Validator Guide

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Developer Guide

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

API & SDK

Loading...

Resources

Loading...

Loading...

Vision & Mision

Vision

Pharos Network is committed to driving trustless innovations that serve financially underserved communities and asset markets, supporting the future global economy and enabling true mass adoption of Web3 technologies.


Mission

The network aims to establish a Web3 infrastructure with the following characteristics:

  • An Inclusive Payment System: Providing a Web2-equivalent user experience at the scale of billions of user accounts globally.

  • An Inclusive Asset Exchange System: Facilitating extreme liquidity for both crypto assets and real-world assets, bridging traditional finance with decentralized markets.

  • A dApp Innovation Platform: Empowering the development of rich Web3 SuperApps through a revolutionary world computing model, leveraging a generic Coprocessor architecture.

Pharos Modular Stack

Pharos Network is designed with a modular and highly parallel architecture, creating a flexible and scalable blockchain stack. At its core, the relationship between the primary network and Special Processing Networks (SPNs) enables seamless execution, enhanced security, and efficient interoperability across different layers of the network. This architecture is built to support high-throughput, trustless innovation at scale.

Key Features of Pharos Modular Architecture

  • Customizable Consensus, Execution, Settlement, and Data Availability Layers: Developer-friendly architecture allows for rapid SPN, Rollup, and SideChain construction within the Pharos Extension Ecosystem.

  • Adaptive Restaking Interaction Protocol: Through the Pharos Restaking Protocol, validators can securely restake across both SPNs and the Primary Network, enhancing liquidity, security, and rewards. This protocol supports native Pharos restaking as well as ETH and BTC restaking mechanisms.

  • Cross-SPN Protocol: Pharos introduces cross-SPN interoperability, enabling seamless communication between SPNs and the primary network. This unified value network allows for smooth asset and data transfer across different execution layers.

Modular Blockchain Stack

Consensus Layer

Pharos supports multiple consensus models, including PBFT, PoS, and PoA, and ensures efficient communication and verification between SPNs and the primary network, allowing for robust and scalable blockchain consensus.

Execution Layer

Pharos offers a dual-execution model that integrates WasmVM & EVM environments. This layer supports standard transaction execution while incorporating advanced computation frameworks like ZK (Zero-Knowledge), TEE (Trusted Execution Environment), and FHE (Fully Homomorphic Encryption). These capabilities enable secure, privacy-preserving transaction processing, ideal for high-frequency trading (HFT), AI applications, ZK-powered dApps, and privacy-focused use cases.

Pharos SPNs are modular and lightweight, capable of acting as specialized networks for execution or as non-blockchain networks, such as for GPU computing, data storage, oracles, and AI infrastructure.

Settlement & Restaking Layer

Validators in the primary network can participate in restaking within SPNs, enhancing both the security and earning potential of the SPN and the Primary Network. SPNs can be quickly launched using the Pharos restaking protocol, ensuring shared security, resource pooling, and incentivizing validators. Restaking helps build enhanced liquidity and security across the ecosystem, forming the foundation for seamless communication between SPNs and the Primary Network.

Data Availability Layer

The Pharos primary network provides data integrity and fast finality, enabling ecosystem projects to enjoy lower costs and greater reliability. For SPNs, the Cross-SPN Protocol combined with native restaking enables second-level finality, a feature that far surpasses traditional subnets and ZK Rollups in efficiency and speed.

Concepts

Degree of Parallelism (DP): Defines the level of parallelization achievable within the blockchain, setting the standard for efficient execution.

Merklization: The process of storing the World State as a Merkle Tree within Pharos Store, with the Merkle Root recorded in the Block Header. Merklization specifically refers to the process of updating State Changes into the World State and recalculating the Merkle Root.

About Pharos Nodes

To build a robust, scalable, and decentralized blockchain network, Pharos implements a thoughtfully designed network topology and consensus mechanism, utilizing three essential node types: Validator Nodes, Full Nodes, and Relayer Nodes, as shown below.

The backbone of Pharos's consensus mechanism is its validator nodes, operating under a Byzantine fault-tolerant (BFT), proof-of-stake protocol. Hundreds of validators work together to secure the network and process user transactions efficiently. Beyond transaction fees and staking rewards, validators can also earn additional revenue through restaking, allowing them to allocate token certificates to SPNs or dApps to enhance scalability, security, and liquidity while earning extra rewards.

Full nodes and relayer nodes support the distribution of blockchain data and provide essential ecosystem services such as state sync, parallel hint generation, indexing, querying, and API services. This structure ensures network integrity, performance, and security.

  • Full Nodes: Storing complete blocks and transaction states, Full Nodes offer crucial support functions. While they do not participate directly in consensus, they facilitate fast state sync to help other nodes quickly synchronize with the latest state and provide parallel hints to validators, enhancing parallel execution efficiency.

  • Relayer Nodes: These lightweight clients store the latest state and handle recent transactions. They provide essential node services, such as transaction simulation and forwarding, and earn rewards by efficiently forwarding messages within the SPNs.

High Performance & Real-Time Processing

Pharos employs an advanced consensus protocol designed for high throughput and low latency, optimized for large-scale nodes across wide-area networks to improve system resilience and security. This consensus mechanism adapts to network delays in real time and maximizes network bandwidth by allowing simultaneous proposals from all nodes, thereby eliminating single-proposer bottlenecks and fully utilizing network resources.

Special Processing Networks (SPNs) and Pharos Nodes

Pharos natively supports SPN deployment. Users can create SPNs by selecting a validator set within the Pharos network. SPNs can adopt entirely distinct protocols, such as private AIoT networks or networks tailored for multi-party privacy-enhancing computations (MPT). SPNs are also compatible with networks requiring TEE hardware for transaction confidentiality and MEV management, as well as networks utilizing specialized hardware.

Degree of Parallelism (DP)

With the growing complexity of Web3 applications, the need for scalability and efficiency becomes paramount. The industry is witnessing a shift towards more powerful parallel processing capabilities to meet the demands of mass adoption. The evolution from sequential processing to highly parallelized architectures marks a significant milestone in blockchain's journey. Significant strides have been made in optimizing L1 network protocols, execution engines, scheduling algorithms, and storage management to enhance overall throughput to the next scale.

To provide a comprehensive view of the existing and future technologies in L1 parallelism, we define the power of network parallelization into distinct Degree of Parallelism (DP) and their expected capabilities in enhancing the performance (p) as follows:

Note: L2 and L3 can work directly with L1 to enhance overall scalability, so they are beyond the scope of our DP definitions and this discussion.

  1. DP0: Sequential Model (p)Linear processing without parallel execution.

  2. CommentDP1: Scalable Consensus (2p~5p)Improved consensus mechanisms with scalability, adaptivity, security and high-performance block propagation ensuring immediate finality.

  3. CommentDP2: DP1 + Parallel Transaction (5p~10p)High-throughput transaction-level parallel processing by leveraging parallel speculation, scheduling, and multi-thread, multi-instruction power.

  4. CommentDP3: DP2 + Pipelining (15p~50p)Incorporates multi-stage pipelined processing, significantly increasing overall throughput and resource utilization while ensuring multi-level-finality and security.

  5. CommentDP4: DP3 + Parallel Merklization and Accelerated State Access (100p~500p)The pinnacle of parallelism, with a unified merklization and indexing scheme to solve IO efficiency and state bloat issues, enabling full parallelism of data access and minimizing storage costs.

  6. CommentDP5: DP4 + Parallel Heterogeneous Computation (500p+)Fully utilize the asymmetric computing power of nodes and support the parallel capabilities of heterogeneous hardware, such as GPU, TEE, FHE accelerator, ZK accelerator and smart network card, to enhance the security of the whole network and applications while comprehensively promoting network parallel capabilities.

The larger the scale of the scenario, the higher DP is required. With the development of Web3 applications, some platforms have recently entered DP3 from DP2. However, to thoroughly address the scalability challenges and ensure mass adoption, transitioning to DP4 is essential.

About Pharos Network

“We believe in: rough consensus and running code” - David Clark, 1992


Pharos Network Overview

Pharos has designed a Modular & Full-stack Parallel L1 Blockchain Network, structured into three primary layers: L1-Base, L1-Core, and L1-Extension.

  • L1-Base: Delivers industry-leading data availability and hardware acceleration.

  • L1-Core: A high-performance, globally distributed blockchain network powered by decentralized nodes. These nodes provide high-throughput and sub-second finality, enabling real-time Web3 user experiences.

  • L1-Extension: Built on top of L1-Core, this layer supports network expansion across three dimensions:

    1. Enables Native Restaking to support rapid SPN creation, shared security, staking rewards, and slashing mechanisms. SPNs utilize the excess computing power of validators, providing flexibility in resource use while incentivizing upgrades.

    2. Facilitates Cross-SPNs Interoperation, allowing infrastructure, middleware, and application-focused SPNs to communicate and collaborate effortlessly, fostering a highly modular and composable ecosystem.


Ecosystem Architecture

The Pharos ecosystem is structured across three key layers:

  1. Transaction Layer: Facilitates secure, confidential, and efficient cross-chain asset and account interactions via the secure and confidential cross-chain interoperability protocol.

  2. Consensus Layer: Integrates with external restaking protocols through the Adaptive Restaking Interaction Protocol, enabling shared security and liquidity. This includes circulating assets like stBTC and stETH within the Pharos DeFi ecosystem.

  3. Data Layer: Uses the Decentralized Data Exchange Protocol to synchronize and collaborate with external data centers, promoting innovative on-chain use cases like AI, FHE.


Pharos Modular Stack

CommentA modular stack is provided to support SPNs, Pharos L2/L3 systems. Each modular component is open-sourced and available to partners and developers for scaling and customization.CommentPerformance benchmarks have been demonstrated on Geth, and future collaborations with ecosystem partners will help drive the development of Web3 infrastructure.


Restaking Integration

Pharos supports a multi-asset protocols to enhance security and liquidity, allowing seamless integration with restaking protocols like Babylon and Eigenlayer. Future updates will include more protocols, expanding interoperability and security across the network.

Leverages heterogeneous computation to create custom , capable of running blockchain networks, sidechains, or non-blockchain applications like HFT, ZKML, and AI models.

Special Processing Networks (SPNs)

Node Architecture

Unlocking the full potential of Web3 requires an efficient, low-latency infrastructure. In our article, Elevating Blockchain Efficiency: A Deep Dive into Scalability and Optimization, we explore the current bottlenecks in blockchain infrastructure. Today’s leading platforms, particularly EVM-compatible L1s and L2s, still fall short of Web2 standards, constraining innovation for Web3 Super DApps. Although high-performance L1 and L2 solutions exist, they are insufficient and often exacerbate liquidity fragmentation. Pharos addresses this challenge through a modular & full-stack parallel L1 blockchain network, a web3 infrastructure that bridges FinTech services and trustless innovation.

Why a modular node architecture?

While monolithic blockchain nodes could theoretically achieve higher performance, we have chosen a modular architecture for three core reasons:

  1. Optimizing Heterogeneous Computation: A modular design allows validator operators to leverage diverse computational resources, advancing our goal of achieving DP5 with Pharos SPN.

  2. Community and Ecosystem Collaboration: By separating modules for consensus, VM, and storage, Pharos invites contributions from community members and ecosystem partners, strengthening Web3 infrastructure.

  3. Enabling Easy Chain Deployment: Our framework, similar to Cosmos SDK or Substrate, empowers developers and projects to build L1s and L2s with efficiency.

Core Technologies

Following the Degree of Parallelism (DP) framework, Pharos uses parallelism at all levels to boost performance, minimize latency, and optimize resources for complex dApps:

  1. Scalable Network and Consensus: A high-throughput, low-latency BFT consensus protocol that fully utilizes network resources.

  2. Dual VM Parallel Execution: A parallel execution layer integrating EVM and WASM with advanced compilation for robust performance.

  3. Full Life Cycle Asynchronous Pipelining: Facilitates parallel and asynchronous transaction lifecycle processing, spanning execution, consensus, and I/O.

  4. High-Performance Store with Authenticated Data Structure (ADS): Delivers high throughput, low-latency I/O, and cost-effective storage, supporting billions of accounts.

Pharos in DP5: Special Processing Networks (SPNs)

Pharos Network pioneers the Special Processing Networks (SPNs) concept, which leverages the security and liquidity of the Pharos Primary Network. Native restaking enables shared security across SPNs and the Primary Network, allowing custom networks to be quickly deployed on heterogeneous validator nodes. This unique approach introduces a generic co-processor design within the world computer model, unlocking the potential of network hardware and diverse local resources.

Pharos Consensus

Pharos employs a consensus protocol that delivers both high throughput and low latency. It is specifically designed for large-scale nodes in wide-area network, enhancing system robustness and consensus security.

There are two design goals of Pharos consensus: responsiveness and the efficient utilization of the whole network's bandwidth. The responsiveness refers to the property that the processing speed of the blockchain system is limited by the actual network delay, without introducing any timeouts or waiting interval. As for the resource utilization, the consensus nodes should have a symmetric communication pattern to work simultaneously.

Most existing blockchain consensus protocols, however, fails to achieve these two goals, resulting in performance and scalability issue. On the one hand, some blockchains set a time interval between two consecutive blocks, so that the block generation is at a fixed rate. As a result, there is an upper bound of the system throughput, no matter how we optimize the network or computing efficiency. On the other hand, the most common communication pattern is prosing-voting. In this pattern, a single proposer is in charge of building and broadcasting the block content, while the others are merely signing and sending the relatively small voting message. Thus, the proposer becomes the bottleneck. As the number of validators increases, more network resource of the proposer is consumed, leading to performance degradation. However, as more validators join, the available bandwidth resource also increases. If we can fully utilize the resource of all the validators, a scalable consensus network can be achieved.

To achieve this goal, Pharos consensus incorporates two innovative features. Firstly, it does not rely on fixed timing assumptions, allowing block generation to be responsive to actual network delays rather than being constrained by a predefined timeout. Secondly, Pharos consensus enables simultaneous proposals from all consensus nodes, eliminating the reliance on a single proposer. These two features significantly enhance scalability and substantially increase the system throughput of Pharos. Furthermore, Pharos consensus introduces a flexible advancement paradigm. Nodes in the new paradigm can propose and commit blocks in a more flexible manner to accommodate various workloads and network condition. For example, a slow and far-away node can propose less frequently, without worrying about its proposal to be suppressed. In our global testbed comprising 100 nodes, the prototype implementation achieves a throughput of over 130,000 transactions per second.

Left: blockchain consensus that generates blocks with fixed time slots and only one validator is allowed to propose within each slot. Right: Pharos consensus allow all validators to propose freely and simultaneously.

Rapid Node Initialization(Testnet)

🧰 Initialization Using Snapshots

Follow these steps to bootstrap a Pharos node using the latest snapshot:

✅ Step1: Download the Snapshot Dataset

We periodically update the latest dataset.

wget https://snapshot.dplabs-internal.com/testnet/snapshot-2025-05-27-03-13.tar.gz
tar -zxvf snapshot.tar.gz

Check this page regularly for updates. Only use snapshots that match your target network.

🧯 Step2: Stop the Container

docker-compose down

🧹 Step3: Remove Local Data and Replace with the Latest Snapshot

rm -rf /data/$WORKSPACE/pharos-node/domain/light/data/public
mv public /data/$WORKSPACE/pharos-node/domain/light/data/public

🚀 Step4: Start the Container

docker-compose up -d

Rapid Node Initialization(Devnet)

🧰 Initialization Using Snapshots

Follow these steps to bootstrap a Pharos node using the latest snapshot:

✅ Step 1: Download the Latest Snapshot

Check this page regularly for updates. Only use snapshots that match your target network.

🧯 Step 2: Stop the Running Node Container

Make sure the node is fully stopped before continuing to avoid data corruption.

🧹 Step 3: Replace Old Data with the Snapshot

Remove the outdated data directory and move in the extracted snapshot:

Adjust the file path to match your actual mount or installation directory.

🚀 Step 4: Restart the Node Container

Your node should now resume from the latest synced snapshot.

We periodically publish . Use the following command to download and extract:

wget https://snapshot.dplabs-internal.com/devnet/snapshot-latest.tar.gz
tar -zxvf snapshot-latest.tar.gz
docker stop pharos-devnet
rm -rf /data/pharos-devnet/pharos-node/domain/light/data/public
mv public /data/pharos-devnet/pharos-node/domain/light/data/public
docker start pharos-devnet
new snapshots

Why A New Blockchain Compute Model

A Dev-Friendly Model for High Performance and Scalable Interoperability

Developer-Centric Tooling and Language Diversity

For this vision to succeed, developers must feel empowered by a robust and intuitive interface. In Web3, the smart contract programming interface is the primary development interface through which they access platform capabilities, a contrast to Web2, where developers often interact directly with programming interfaces, databases, and other essential components.

Our model provides a comprehensive suite of tools, SDKs, and support for a wide range of programming languages. Web3 should be open and accessible—not exclusive—creating an environment where developers of any language or experience level can seamlessly build, test, and deploy their ideas. This model supports every stage of the development lifecycle, from tooling and debugging to deployment, fostering a cross-functional environment that welcomes diverse developer groups without confining them to a single language or toolkit. By embracing multi-language support, we prevent the fragmentation often seen when developers are restricted to specific languages, building a truly diverse and inclusive ecosystem.

Seamless Liquidity with Native Interoperability

In a multi-chain ecosystem, liquidity and seamless interoperability are essential. Developers should be able to write contracts in one language and easily call them from another without added complexity. Our model enables multi-language smart contract development with native, frictionless cross-contract interoperability, reducing costs by eliminating the need for redundant VMs, inter-process communication overhead, and nested VM execution. This approach benefits not only developers but also lightens the computational load on blockchain infrastructure.

Additionally, our compute model supports dynamic, multi-dimensional interaction models—from one-to-one to many-to-one—spanning intra-process, inter-process, and cross-chain interoperability. This flexibility allows developers to structure interoperability according to their application's unique needs rather than adapting to constraints imposed by the compute layer.

Collaboration with Heterogeneous Systems and Co-Processors

One of the most exciting aspects of this model is its compatibility with diverse compute units and external co-processors. Imagine a blockchain VM that can natively interact with external accelerators, such as SIMD for parallel computing, GPUs for high-intensity AI tasks or zkVMs for zero-knowledge proofs. This extensibility aligns perfectly with modern compute demands, making the blockchain platform as adaptable as any in the Web2 landscape.

By enabling co-processor compatibility, developers can now create blockchain solutions that were previously unimaginable. On-chain AI inference and zero-knowledge proofs become feasible while preserving blockchain's core security and transparency. This marks a significant step forward in expanding on-chain capabilities available to developers. Application developers can access co-processor capabilities seamlessly, as intuitively as writing standard code—this is where the magic of the new compute model truly shines.

This shift will also attract specialized talent to upstream library development, where domain experts can leverage performance-enhancing tools like ZKP and GPUs, unlocking their full potential for blockchain innovation and freeing these capabilities from being confined within the platform itself.

Security and Privacy

Our model simplifies security management across various smart contracts through a unified, automated security auditing and formal verification tool. Additionally, by integrating ZKP and advanced encryption technologies, it protects user privacy while ensuring transaction authenticity. This suite of technologies not only strengthens the security of blockchain applications but also enhances the overall trustworthiness and sustainability of the ecosystem.

Real-World Applications: A Platform for Limitless Possibilities

The transformative potential of this model is vast. Imagine global micropayments processed without prohibitive transaction fees or on-chain games with real-time data and seamless interactions. With co-processor integration, AI models could run directly on-chain, enabling real-time inference for applications ranging from fraud detection to personalized content recommendations. Cross-chain protocols would also gain, benefiting from increased reliability and reduced complexity, as this VM supports a broad array of network standards and data structures.

A Vision for Blockchain Compute

Looking to the future, the path of our compute model is as varied as the possibilities within Web3. Should we focus on specialization or broader generalization? Aim for EVM compatibility or adopt a more generalized, high-performance approach similar to Solana's? Do we prioritize Python's accessibility or lean into Rust's system performance? These questions guide us in creating a compute environment that not only meets blockchain's current demands but also adapts to the rapid pace of technological and developer evolution. With advancements in compiler technology, we also consider when the time is right to transition fully to a compiled VM model.

Our compute model embodies a vision of unmatched performance, widely adopted standards, developer flexibility, and seamless interoperability. By pushing beyond current limitations and anticipating Web3's future needs, we're establishing a foundational compute layer poised to drive the next era of blockchain innovation.

Validator Requirements

To ensure a validator operates effectively and efficiently, the minimum recommended hardware specifications are:

Component
Specification

CPU

16 cores, 2.8GHz or faster, AMD Milan EPYC or Intel Xeon Platinum

Memory

32 GB RAM

Storage

2 * 1TB SSD with at least 230MiB/s bandwidth and 10000 IOPS

Network Bandwidth

0.5 Gbps

Using Docker (Devnet)

Prerequisites

Before starting, ensure that you meet the system requirements for Pharos nodes. Additionally, install the following dependencies:

  • Docker

Deployment Steps

docker pull public.ecr.aws/k2g7b7g1/pharos:latest
docker run -d --name pharos-devnet -v /data/pharos-devnet:/data -p
18100:18100 -p 18200:18200 -p 19000:19000
public.ecr.aws/k2g7b7g1/pharos:latest

Parameter Explanation

  • -name pharos-devnet: Container name, customizable.

  • -v /data/pharos-devnet:/data: Local mount directory, recommended to be set on a high-capacity disk.

  • public.ecr.aws/k2g7b7g1/pharos:latest: Pharos Devnet image address.

In your mount directory there should be a list of files:

  • deploy.light.json: Pharos binary configuration template

  • domain.json: Pharos deployment configuration file

  • genesis.conf: The genesis config of the devnet you are connecting to

And the following directories:

  • pharos-node: Pharos deployment directory, Contains configuration files, binaries, logs, DB, etc.

  • pharos-node-client: Pharos client directory, used to do node management

  • resources: Node's keys directory, including consensus signing key and BLS key. Keep it safe

Node Management

Node Initialization

Pharos Full Nodes automatically generate cryptographic keys on startup — no manual configuration is needed. To start a validator node, run the following command in your working directory:

docker start pharos-devnet

Entering the container

docker exec -it pharos-devnet /bin/bash

Join validator sets

If your full node has synced up with the latest block, you can convert it to a validator.

If you need to join Pharos Devnet as a Validator, please contact and send domain file and pubkeys to [email protected] or TG (@janesh_dani)

⚠️ Note: If more than one-third of validators go offline, the Devnet may halt due to consensus safety constraints.

⚠️ To join the network, the corresponding account needs to stake a certain amount of tokens. Please contact us to obtain the staking tokens.

  • Pack needed files into node_info.tar.gz

    • tar -zcvf node_info.tar.gz /data/pharos-devnet/domain.json \ /data/pharos-devnet/resources/domain_keys/prime256v1/domain/new.pub \ /data/pharos-devnet/resources/domain_keys/bls12381/domain/new.pub

    • tar -zcvf node_info.tar.gz /data/testnet/domain.json \ /data/testnet/resources/domain_keys/prime256v1/domain/new.pub \ /data/testnet/resources/domain_keys/bls12381/domain/new.pub

  • Domain config:

    • /data/pharos-devnet/domain.json

  • Node pubkeys:

    • /data/pharos-devnet/resources/domain_keys/prime256v1/domain/new.pub

    • /data/pharos-devnet/resources/domain_keys/bls12381/domain/new.pub

Rapid Node Initialization

To help developers and validators quickly join the Pharos Network without syncing from genesis, we provide regularly updated snapshot datasets for each network. These snapshots contain pre-synced state data and allow rapid setup of Devnet, Testnet, or Mainnet nodes.

⚠️ Snapshots should only be used from trusted sources. Always verify integrity before replacing production data.


Pharos Network

  • Testnet

  • Devnet

💡 Notes & Best Practices

  • Snapshots currently contain the full block history. In the future, we will support pruned snapshots that include only the most recent blocks and state.

  • Archive nodes should still sync from genesis.

  • After applying a snapshot, the node will continue syncing to the latest height.

  • Always ensure your snapshot corresponds to the correct network and version.

Pharos Node Monitoring

We recommend deploying Prometheus, Pushgateway, and Grafana to monitor Pharos Node metrics.

Deploy Prometheus and pushgateway

If you have already deployed a Prometheus monitoring and alerting system, you can skip this step:

  1. Create the Prometheus namespace:

kubectl create namespace prometheus
  1. Add the prometheus-community chart repository:

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
  1. Deploy Prometheus:

helm upgrade -i prometheus prometheus-community/prometheus \
--namespace prometheus \
--set alertmanager.persistence.storageClass="gp2" \
--set server.persistentVolume.storageClass="gp2"
  1. Verify that all pods in the prometheus namespace are in the READY state:

kubectl get pods -n prometheus
  1. Get the Pushgateway Service IP/Domain:

kubectl -n prometheus-agent-namespace get svc

You should see the prometheus-pushgateway Service. Save the IP address of the Pushgateway Service.

Modify the metrics push configuration file

Modify /data/pharos-node/domain/light/conf/monitor.conf with the pamir_cetina_push_address to push metrics to your Pushgateway:

{
  "enable_pamir_cetina": true,
  "pamir_cetina_push_address": "your_pushgateway_domain_or_ip",
  "pamir_cetina_push_port": 9091,
  "pamir_cetina_push_interval_second": 5,
  "pamir_cetina_job_name": "pharos_testnet_xxx"
}

Pharos VM

A Next-Generation Virtual Machine for Blockchains

The Pharos VM also known, is a cutting-edge virtual machine designed to bring exceptional performance, stability, and interoperability to the blockchain space.CommentGive feedback on the editor

What is Pharos VM?

CommentGive feedback on the editorPharos VM is essentially a high-performance environment where smart contracts are executed on the blockchain. The virtual machine not only processes transactions but also compiles and optimizes smart contract code to run more efficiently. Its design goal is to serve as a robust Ethereum-compatible virtual machine that operates seamlessly within Layer 1 and Layer 2 solutions. This allows it to execute Ethereum-compatible (EVM) smart contracts while also supporting WebAssembly (WASM), thus accommodating a wide range of programming languages and tools.CommentGive feedback on the editor

Highlights of Pharos VM

  1. Super-fast and Cost-efficiency

  2. Dual VM Spec Support

  3. Dev-Friendly Toolings and Languages

  4. Native Interoperability

  5. Extensibility and Flexibility with co-prosoccers

  6. Built-In Security and Verification

How Pharos VM Stands Out

High-Level Optimizations: Pharos VM’s compilation process includes powerful optimizations such as SIMD, data caching, opcode fusion, register promotion. By optimizing both CPU-bound and I/O-bound contract operations, Pharos VM reduces resource use and enhances speed, making it ideal for high-performance blockchain applications.

Dual VM Specifications: Pharos VM supports both EVM and WASM smart contracts under a single runtime environment, eliminating the need for separate virtual machines for each type. This unified approach simplifies execution and allows efficient cross-contract interoperability without performance sacrifices.

Advanced Parallel Execution: Designed for peak performance, Pharos VM can execute multiple tasks in parallel, identifying dependencies and minimizing resource contention. It even includes speculative execution capabilities to predict and preload frequently accessed data, further enhancing speed.

Performance

Pharos VM has shown excellent performance in foundational benchmarking tests. The following graps serves as a reference for understanding its performance, with all tests conducted on a personal Mac Pro without additional optimizations. We will continue optimizing its performance and regularly update performance data.

Why Pharos VM Matters

For developers, Pharos VM offers a highly compatible and efficient environment that can execute Ethereum smart contracts with greater speed and lower costs. By supporting both EVM and WASM with native interoperability, Pharos VM enables a broader array of applications and allows the blockchain ecosystem to move beyond traditional constraints.

For blockchain users and organizations, Pharos VM promises a more secure and reliable environment for transactions. With built-in verification and safety mechanisms, it reduces the risk of bugs and vulnerabilities, adding a layer of trust to smart contract interactions.

In conclusion, Pharos VM represents a new era of blockchain virtual machines, combining compatibility with existing platforms and the flexibility to evolve alongside the fast-changing blockchain ecosystem. It offers the blockchain community a fast, secure, and interoperable environment to execute and optimize smart contracts, making it a promising choice for both current and future decentralized applications.

Enable AutoPruning in Pharos Node

1. Step1: Node Status Verification

You can use the RPC API to check whether the node is actively running.

curl 127.0.0.1:18100/ \\
  -X POST \\
  -H "Content-Type: application/json" \\
  --data '{"method":"eth_blockNumber","params":[],"id":1,"jsonrpc":"2.0"}'

2. Step2: Enable Pruning

Enter the container pharos-testnet and use the tool to enable auto-pruning

docker exec -it pharos-testnet /bin/bash
cd /data/pharos-node/domain/client/bin/
LD_PRELOAD=./libevmone.so ./pharos_cli prune --enable_auto_prune

Once the above operations are complete, the node will automatically begin pruning its database.

3. (Optional)Step 3: Query Pruning Settings

Following the preceding steps, you may now query the pruning configurations

docker exec -it pharos-testnet /bin/bash
cd /data/pharos-node/domain/client/bin/
LD_PRELOAD=./libevmone.so ./pharos_cli prune --get

In the output logs, you can see the following information:

PruneInfo:
enable_auto_prune: 1
auto_prune_reserved_window: 100000
prune_reserved_version: xxxxxx
flushed_version: xxxxxx
real_prune_reserved_version: xxxxxxx

If enable_auto_prune is set to 1, it indicates that auto pruning has been enabled.

Validator Node Deployment

Deploying Pharos Nodes

Before running a Validator Node or Validator Full Node (VFN) on the Pharos Network, you must choose a deployment method and ensure your machine meets the required specifications.

This guide provides clear instructions for deploying nodes using different methods. Once deployed, you can connect your node to the Pharos network and begin participating in consensus or network operations.

📘 Note: Please review the Node Requirements before choosing a deployment method.

Deployment Methods

Choose one of the following deployment methods to set up your node:

🐳 Using Docker

  • Devnet

  • Testnet

🔧 Using Source Code (Coming Soon)

Interoperability

This guide is suitable for developers who want to realize interoperability between EVM and WASM. If you are a new user of Ethereum, please consider researching the Ethereum documentation before continuing.

Why Pharos Network

Elevating Blockchain Efficiency: A Deep Dive into Scalability and Optimization

Blockchain technology has made significant strides in recent years, yet performance remains a primary bottleneck hindering the Web3 user experience. Although many protocols achieve high TPS in ideal or test environments, their performance in real-world falls far short of expectations. This performance gap makes it difficult for Web3 applications to compete with Web2 applications, limiting their mass adoption and enhancement of user experience.

For instance, with bitcoin inscription frenzy hits EVM blockchains in early 2024, we observed that most public chains could not exceed a thousand TPS(Transaction Per Second), typically ranging from dozens to a few hundred. Some public chains, under high-stress conditions, opted to raise Gas Prices to reduce transaction frequency, but this is neither a healthy nor sustainable solution. In fact, the execution cost of smart contracts is usually far higher than that of inscription transactions. Given the current infrastructure, most public chains are still unable to support the operations of Web3 Super DApps, which is one of the crucial factors constraining the current development of Web3. Paradigm also provided some insightful data.

Three Major Challenges Towards High-Performance Blockchains

After extensive research and testing, Pharos has identified three significant challenges currently facing high-performance Web3 blockchains:

  • Challenge 1: The "Bottleneck Effect" in Blockchain

    Throughout the development of programmable blockchains, many developer and researchers have continuously optimized various modules, such as consensus, execution, and storage. However, due to the complexity of blockchain systems, isolated optimizations often fail to address overall performance issues, resulting in a limited improvement in end to end transactions per second (TPS). This phenomenon is what we refer to as the “Bottleneck Effect” in blockchain. This issue is particularly pronounced in traditional sequential execution blockchain networks. For instance, in a simulation of Ethereum’s transaction on a Geth client running on a single node (32GB RAM, 16 cores, 2TB SSD), we observed the following time distribution across different stages under continuous load pressure. Although many Layer 1 and Layer 2 solutions focus on optimizing performance from the perspective of executing transactions (e.g., Parallel EVM), they still face bottlenecks in merklization and database operations, which limit overall blockchain network performance. Consequently, in the past 1-2 years, we have seen blockchains, such as Avalanche, Monad, and Sei Network, proposing their own database and merklization solutions.

  • Challenge 2: The Need for Decentralized & Large-Scale Networking

    Blockchain is a decentralized distributed ledger system that must support efficient transaction execution and RPC services while maintaining decentralization and large-scale networking at a low cost to enhance network reliability and asset security. However, high hardware requirements can limit the network scale, reducing its security and degree of decentralization. The chart below shows the current hardware requirements for Validators/Sequencers on some L1 and L2 networks:

    Blockchain
    CPU (cores)
    Memory (GB)
    Network (Gbps)
    Storage (TB SSD)
    TPS
    Validator

    Ethereum

    4

    16

    0.025

    2
    30

    1.5 Million

    Solana

    12

    256

    1~10

    2
    65000

    ~1,500

    Aptos

    32

    64

    1

    2
    30000

    ~150

    Monad

    16

    32

    0.1

    2
    10000

    -

    Reth

    (Single Node)

    24

    256

    10

    2
    20000

    1

    Mega ETH

    (Single Sequencer)

    100

    1024~

    4096

    10

    2
    100000

    1

    In reality, most personal computers and mobile devices already have decent configurations, and some L1 and L2 networks are considering incorporating them into their ecosystems.

  • Challenge 3: State Bloat Problem Hinders Blockchain Development

    In Why We Need a Blockchain-Native Store, we explore the main bottlenecks facing current blockchain storage systems. With the increase in blockchain users, state bloat has led to challenges such as performance degradation, network scalability limitations, and resource inefficiencies. These issues create significant barriers to the large-scale, production-ready deployment of most L1 and L2 networks.

Shortcomings of Existing Solutions

Pharos, considering the current state of monolithic chains and modular ecosystems, has identified four key shortcomings in the performance optimization of existing blockchains:

  • Insufficient "Parallelism"

    The "parallelism" in existing blockchains is limited, particularly between the execution and storage layers.

    1. Execution Layer: While Parallel EVM technology enhances efficiency, actual parallelism remains below ideal levels due to limitations in optimistic execution algorithms and disk I/O speed. The current Parallel EVM framework also struggles to accommodate the diverse scenarios and execution logic of various DApps, especially AMM-based DEXs.

    2. Storage Layer: Most blockchains use traditional key-value stores and Merkle Tree structures, limiting concurrency in both I/O access and merklization. Teams like Reth and Monad have recognized this issue and are exploring async I/O and parallel merklization to overcome these bottlenecks.

  • Verifiable Storage Remains a Bottleneck in Large-Scale Scenarios

    Most current L1 and L2 solutions still rely on verifiable storage architectures, but their inefficient querying and merklization performance severely limit overall blockchain throughput. The combination of MPT (Merkle Patricia Tree) and LSM Store, for instance, faces three performance issues: Long I/O Paths, Hash-Based Addressing, and State Bloat. As State Bloat worsens, the efficiency of starting new nodes continues to decline, further impacting network scale and decentralization.

  • Insufficient Utilization of Node Resources

    The resources of existing blockchain nodes are not being fully utilized. One reason is that, in traditional blockchain models, CPU and I/O resources remain idle for much of the time. Furthermore, on-chain data and index maintenance also waste a significant amount of CPU and I/O resources. Taking the most typical LSM Database as an example, compaction consumes considerable CPU and I/O resources, competing with existing modular components and greatly reducing throughput.\

    In the Why We Need Pipelining section, we provide a detailed overview of the resource bottlenecks at each stage of blockchain processing.

  • Limitations of Layer 2 Scaling Solutions

    While many Layer 2 (L2) solutions (such as ZK/OP Rollup, and Sidechains) have proven effective in improving Layer 1 (L1) scalability, several issues still persist:

    • Increasing State Bloat in L2:

      Most L2 sequencers continue to use traditional blockchain node architectures, which do not effectively address the state bloat problem, resulting in significant throughput limitations. Many L2 networks only achieve between tens to a few hundred TPS, as shown in Paradigm's recent performance data for various L2 solutions. Moreover, while decentralized sequencer networks are an aspirational goal for many L2 projects, they encounter technical challenges as complex as those faced by L1 networks. In ZK rollup designs, this problem is often compounded by the use of binary Merkle trees, which further intensify state bloat.

    • Data and Liquidity Fragmentation:

      While L2 solutions enhance scalability, they introduce significant delays in inter-network communication. For example, rollups typically require several hours to days for messages to transfer from L2 to L1 during the challenge period, slowing down communication and leading to severe data and liquidity fragmentation. Additionally, L2 networks cannot share assets and account states directly with each other and must rely on third-party bridges for transfers, which introduces both centralization and security risks.

The Right Path to Improving Blockchain Scalability

In the current blockchain ecosystem, isolated optimizations often fall short of expectations. A holistic approach is necessary, considering consensus, execution, storage, and parallel processing.

Pharos introduces a suite of efficient modular components and parallel solutions, with a sustained focus on research and practical advancements in this field. We aims to deliver high-performance, low-latency, and cost-effective blockchain services, bringing a Web2-like user experience to Web3.

FAQ

Problem Explanation

Ethereum's execution model deducts the full gas limit at the start of execution and refunds a portion of the gas at the end if applicable. However, if the gas limit is set too tightly (equal to the actual gas used before refunds), the refund cannot be processed, and the transaction fails with an out-of-gas error.

Key reasons why this happens:

  • Gas is initially reserved: The EVM deducts the full gas limit at the beginning of execution.

  • Gas refund happens at the end: If a contract includes operations that delete storage variables (e.g., SELFDESTRUCT, SSTORE clearing a slot), the gas refund is only applied after execution completes.

  • If gas runs out before refunding, the transaction fails because the EVM does not get a chance to apply the refund.

Example Scenario

Below is an example of a Uniswap V3 transaction deployed on Pharos Devnet, where the actual gas used was 4,618,680: https://pharosscan.xyz/tx/0x205a123820ad75de162ba3cabe06183d34377e239c3a8f6f18636d4c87b3a524

However, since the gas limit was set exactly equal to the gas used, the transaction failed.

To verify this behavior, we deployed the same transaction on Ethereum Sepolia Testnet, and observed the same failure due to the gas limit issue: https://sepolia.etherscan.io/tx/0x55af4ffe714ad075c6f979e7f89670e1498647abedd6ea7112e1c6339cef64aa

To ensure the transaction executes successfully, we need to set the gas limit slightly higher than the expected gas usage. https://pharosscan.xyz/tx/0x6ccf7f593f5783414b3726e147319e74046526d800b325110bdf81ac3012aa5e

Pharos Networks

Pharos Testnet

Pharos Devnet

Pharos Gas Model

Understanding Gas Refund and Gas Limit in Pharos Transactions

Overview

When sending a transaction on Ethereum or an EVM-compatible blockchain, it is essential to set an appropriate gas limit to ensure successful execution. One common issue arises when the gas limit is set exactly equal to the gas used, particularly when the transaction involves a gas refund mechanism.

Summary Table

Best Practices for Developers

  • Set a slightly higher gas limit: Allow extra gas beyond the expected execution cost.

    • Example: If you expect 100,000 gas used before refund, set the gas limit to 120,000 to avoid failures.

  • Use Estimation APIs:

    • When sending transactions via Web3 libraries (ethers.js, web3.js), always use estimateGas() and add a buffer.

    • Example (ethers.js):

  • Monitor Gas Refund Logic:

    • If your contract relies heavily on gas refunds (e.g., clearing storage or SELFDESTRUCT), test transactions with different gas limits to find an optimal value.

  • Check for Out-of-Gas Failures:

    • If a transaction fails unexpectedly despite having enough gas, check whether gas refunds are affecting execution.

    • Debug with debug_traceTransaction or EVM logs.

Conclusion

To prevent transactions from failing due to gas refund issues, always set a gas limit slightly higher than the expected gas usage. This ensures smooth execution and prevents out-of-gas errors caused by refund mechanisms.

By following these best practices, developers can avoid failed transactions and improve the reliability of smart contract interactions.

Name
Pharos Testnet
Name
Pharos Devnet

RPC Public Endpoint

https://testnet.dplabs-internal.com

WSS Public Endpoint

wss://testnet.dplabs-internal.com

Explorer

https://testnet.pharosscan.xyz

ChainID

688688

Environment

Testnet

Ratelimit

500 times/5m

Max Pending TXs (Addr)

64

RPC Public Endpoint

https://devnet.dplabs-internal.com

WSS Public Endpoint

wss://devnet.dplabs-internal.com

Explorer

https://devnet.pharosscan.xyz/

ChainID

50002

Environment

Devnet

Ratelimit

500 times/5m

Max Pending TXs (Addr)

64

Feature

Details

Opcode pricing

Fully aligned with Ethereum EVM opcode gas table

EIP-1559 support

✅ Compatible (base fee + priority fee)

Base fee

Dynamic (will re-calculate per epoch)

Transaction fee model

Charged by gas_limit at inclusion time

Refund logic

Full EVM-style refund tracking supported, but refund does not affect charge

const estimatedGas = await contract.estimateGas.someFunction();
const gasLimit = estimatedGas.mul(12).div(10); // Adding a 20% buffer
await contract.someFunction({ gasLimit });

Pharos Execution

Parallel Execution Framework

Pharos Execution is the engine powering the Pharos network, designed for exceptional performance, scalability, and efficiency. The architecture comprises two key components: the scheduler and the executor. The scheduler is a core component for parallel scheduling and executing transactions, utilizing optimized algorithms for maximum parallelism and minimal conflicts. The executor features dual virtual machine (EVM and WASM) engines for fast and flexible smart contract execution. The EVM engine ensures compatibility with solidity contracts, while the WASM engine provides high-performance execution for a wider set of smart contract languages.

Architecture

Pharos adopts a parallel approach to transaction execution, focusing on:

  • Optimal Grouping: Near-optimal parallel transaction groups with high concurrency.

  • Extreme Performance: Fast transaction execution with integrity and correctness. Efficient transaction validation, deterministic finality, and conflict handling.

Pharos ensures parallel execution efficiency and deterministic finality through:

  • Parallel Hint Generation: Leveraging static analysis and speculative execution of smart contracts, Pharos generates accurate read-write set hints to minimize conflicts and enhance parallelism. This is achieved through a robust compilation framework and a fine-grained analysis algorithm, providing comprehensive control and data flow insights to reduce runtime overhead.

  • Transaction Dependency Analysis: Pharos analyzes transaction dependencies using read-write sets and generates parallelizable transaction groups with the union-find algorithm. These groups are aligned with the number of execution workers, and all state objects for each group are preloaded in a single batched I/O operation, significantly reducing execution time.

  • Optimistic Execution & Pipeline Finality: Pharos utilizes optimistic execution alongside a "Pipeline Finality" algorithm, allowing quick convergence of execution results and determining the final state efficiently.

Pharos is continuously improving its parallelism by:

  • Efficient Resource Management: Validators balance tasks such as speculative execution, fully utilizing multi-core CPUs and I/O resources while allowing executors to take on scheduling work, optimizing overall resource use.

  • Global Data Optimization: Parallel and storage optimization of global data with read-write set conflicts, such as global counters, further enhances performance.

  • Conflict Detection & Minimal Re-execution: Through fine-grained control, Pharos achieves faster conflict detection and minimal-cost re-execution, delivering optimal parallel performance.

Pipeline Finality

In Full Life Cycle Async Pipelining,we divide the finality of transactions into the following three categories::

  • Ordering Finality: Ensures permanent transaction sequencing.

  • Transaction Finality: Provides deterministic execution results.

  • Block Finality: Allows immediate access to finalized blocks.

In the Pharos Parallel Execution Framework, Transaction Finality is prioritized to ensure a seamless Web3 user experience, while we aim to minimize the delay in Block Finality. This is crucial as infrastructure components like oracles and indexers rely on this information. To optimize block finality, Pharos employs the following techniques:

  • Setting a maximum finality time for each block (e.g., n blocks, where n = 10).

  • Faster BlockHeader Generation: Performance-optimized validators or RPC nodes may generate block headers faster, broadcasting them to other nodes that perform verification and application without full computation (via state sync).

Execution Framework Overview

The Pharos Parallel Execution Framework operates through the following seven steps:

  1. Consensus the latest block batch and synchronize parallel execution hints across the network.

  2. Split execution groups using dependency graphs based on the parallel hints.

  3. Sequentially process transactions within each group in the executor.

  4. Load merklized state data in parallel to optimize performance.

  5. Identify and resolve execution conflicts between concurrent groups.

  6. Redo some transactions in the groups and generate the finality status.

  7. Write the updated state using asynchronous I/O.

Our algorithm is designed to minimize Transaction Finality time, while Pharos Store assists by preloading merklized state data (e.g., MPT, JMT nodes), accelerating block header generation and block finality consensus.

Pharos Store

The Future of Blockchain Storage

Pharos Store Architecture

To address the limitations posed by state bloat, Pharos Store was developed as the first blockchain-native, verifiable storage solution, offering high-performance read/write capabilities and efficient merklization. Compared to traditional blockchain storage solutions, Pharos Store achieves up to 15.8× throughput and 80.3% storage cost savings [1].

In the article Why We Need a Blockchain-Native Store, we discuss the three main challenges facing blockchain storage today: Long I/O Paths, Hash-Based Addressing, and State Bloat. Pharos Store tackles these issues through several key design innovations:

Innovations 1: Authenticated Data Structure (ADS) Pushdown

Pharos Store integrates the Authenticated Data Structure (ADS) directly into the storage engine, eliminating the boundary between ADS and backend storage to enable fine-grained I/O optimization. This is achieved through three core components:

  • DMM-Tree (Delta-encoded Multi-version Merkle Tree): A built-in multi-version Merkle tree that supports dictionary trees, B-trees, and other tree structures.

  • LSVPS (Log-Structured Versioned Page Store): Provides a page index abstraction between memory and secondary storage for the DMM-Tree.

  • VDLS (Versioned Data Logging Stream): Stores user metadata in an append-only manner.

By integrating ADS with the storage engine, Pharos Store eliminates the Long I/O Path problem that plagues traditional two-layer architectures (e.g., Merkle Tree + KVDB), becoming the first Blockchain Native ADS Store.

Innovations 2: Version-Based Addressing

Pharos Store replaces hash-based addressing with version-based addressing, which eliminates the need for file compaction by ordering data according to version numbers.

Both logically and physically, each leaf node in a DMM-Trie records the block number corresponding to its child nodes, unlike hash-based addressing methods (e.g., MPT, IAVL, ZKTrie). DMM-Trie uses V (the most recent version) + NodeIndex to locate internal nodes and leaf nodes in sequence. Each node and page in the DMM-Trie retains V and the V of its children.

Innovations 3: Minimizing "State Bloat" through Internal Compactions, Page Storage, and Delta Encoding

To mitigate the impact of State Bloat, Pharos Store adopts the following techniques:

  1. Internal Compactions to reduce node path length.

  2. Persistent storage at the subtree level, where pages are used as the minimal persistence unit written to storage.

  3. Delta Encoding: Persists tree nodes using delta encoding, storing only modified data to reduce I/O and space amplification.

By employing these techniques, Pharos Store reduces ADS storage space and bandwidth consumption to less than 20% of traditional models.

Conclusion

As the first blockchain-native ADS storage solution, Pharos Store is compatible with MPT, JMT, and ZKTrie, significantly improving single-node performance, especially in large-scale data environments and complex contract scenarios. More detailed information will be released soon, and we welcome more teams and projects to join us!

Pharos Pipelining

Full Life Cycle Async Pipelining

Why We Need Pipelining

While blockchain technology has evolved substantially, transaction execution efficiency remains a major bottleneck, limiting throughput and overall performance. Traditional blockchain architectures encounter several resource-intensive hotspots that constrain their capabilities.

The above figure shows the time breakdown of different stages in the Geth client during sequential execution. Other blockchain clients exhibit similar stages, though with variations due to database design differences. Key resource hotspots in traditional blockchain systems include CPU Utilization, Disk I/O, and Network bandwidth.

1. CPU Utilization: CPU resources are heavily taxed in blockchain operations, especially during execution, merklization, and various database operations (e.g., compaction and pruning). Merklization, in particular, is CPU-intensive, which becomes especially challenging at larger data scales.

3. Network: Consensus mechanisms rely on extensive network communication, making both bandwidth and latency crucial to overall system performance.

These constraints underline the need for an optimized pipelining mechanism to address these resource hotspots effectively, streamlining the transaction execution process and enhancing blockchain performance.

What is a Good Pipelining Mechanism?

A well-designed pipelining mechanism can significantly improve blockchain performance by ensuring efficient resource utilization and minimizing bottlenecks. The key components of an effective pipelining mechanism include:

  • Synchronization and Coordination: Ensuring smooth data flow and alignment across different stages is crucial. This involves maintaining data consistency and providing reliable responses within a decentralized environment.

  • Resource Management: Effective pipelining dynamically allocates CPU, network, and I/O resources in real-time. Concurrency control is essential to prevent contention and race conditions, ensuring that resources are used optimally.

  • I/O Optimization: Reducing read/write latency and efficiently managing large-scale data are critical for maximizing parallelism during execution. This helps to minimize the delays associated with I/O operations.

  • Network Considerations: Ensuring fast and reliable data propagation is necessary for maintaining fault tolerance and enabling smooth recovery from network faults.

The Challenges of Designing Pipelining

Designing an effective pipelining mechanism involves overcoming several significant challenges:

  • Accurate control of read and write concurrency under multi-versions data: Managing multiple data versions without causing read/write conflicts is a complex task that requires precise control mechanisms.

  • Disk reads significantly impact parallel execution efficiency: High-frequency disk access can create bottlenecks in parallel processes, reducing overall execution efficiency.

  • Competition for CPU and I/O resources with executors: Ensuring that executors have sufficient resources while balancing the needs of other processes is critical to maintaining performance.

  • Real blocks can only be generated after consensus broadcast: Consensus completion is necessary before finalizing blocks, adding complexity to the pipelining process and requiring careful coordination.

Pharos Pipelining

Pharos deconstructs all blockchain processes into six essential stages to optimize the utilization of network, disk I/O, CPU, and other system resources. This approach achieves three major advantages: high TPS, low latency, and enhanced security and reliability:

  1. High TPS: Pharos minimizes disk I/O during execution and merklization stages, taking full advantage of multi-core processors to achieve high throughput.

  2. Low Latency: Resources are prioritized for the transaction finality of the latest block, ensuring that most Web3 users experience low latency in their operations.

  3. Security and Reliability:

    • Data Integrity: Ensures that no data is lost at any finalized stage, even if all validators fail simultaneously.

    • Rapid Resynchronization: Validators can quickly recover and update to the latest state after a crash.

    • Consistent Data Management: Strict management of reads and writes prevents data inconsistencies during parallel processing.

By leveraging three key solutions—Parallel Block Stages, Dynamic Resource Allocation, and Flexible Finality—Pharos sets the foundation for more robust and responsive Web3 applications, effectively addressing the performance limitations inherent in traditional blockchain systems.

1. Parallel Block Stages: Pharos allows different stages between blocks to be executed simultaneously, boosting throughput and lowering latency.

2. Dynamic Resource Allocation: By recognizing that different time slices have different resource preferences, Pharos improves resource management and reduces storage bottlenecks.

3. Flexible Finality: Pharos accommodates varying finality requirements for SDKs, clients, and nodes, enabling efficient resource allocation and faster confirmations.

  • Ordering Finality: Ensures permanent transaction sequencing.

  • Transaction Finality: Provides deterministic execution results.

  • Block Finality: Allows immediate access to finalized blocks.

Pharos Testnet Information

Important Contracts

Testnet Tokens

Why We Need a Blockchain-Native Store

The continuous growth of state bloat presents the following issues:

1. Performance Degradation: Most L1 and L2 networks incur significant costs in retrieving the state of target accounts and contracts during contract execution, and the retrieval efficiency decreases as the data volume increases. Larger data volumes prevent typical validators from caching all the state data required for transaction execution. Particularly in scenarios involving billions of users, most transaction executions require disk access, significantly increasing database read times, leading to performance degradation and higher latency. This is one of the reasons why most L1 and L2 networks perform worse in public environments than in experimental settings.

2. Network Scalability Limitations: For example, synchronizing an Ethereum node often takes several days or even weeks, severely restricting network node scalability.

3. Resource Waste: Using databases like LevelDB and RocksDB to store merklized state results in significant write amplification and bandwidth consumption, particularly in MPT and IAVL trees.

Current Blockchain Storage Limitations

Most current L1 and L2 solutions still rely on verifiable storage architectures, but their inefficient querying and merklization performance severely limit overall blockchain throughput. The combination of MPT (Merkle Patricia Tree) and LSM Store, for instance, faces three performance issues: Long I/O Paths, Hash-Based Addressing, and State Bloat.

Problem 1: Long I/O Paths:

As illustrated in Figure 5, the existing WorldState is stored in an LSM Store in a Merklized State data format, with its Root value anchored in the block header. The account and contract data required for each transaction execution are stored in the leaf nodes of the Merkle Tree. Indexing these requires loading all nodes along the path from the root to the leaf, resulting in excessively long data access paths, increased I/O latency, and reduced data reading efficiency.

In the Ethereum mainnet, the Merklized State data volume ranges between 500GB and 1TB (after archiving). Storing this data in databases like RocksDB or LevelDB results in about five levels of compaction. Due to the randomness of hashing and the impact of the compaction mechanism, a single Merkle node may require tens or even dozens of disk accesses. In actual testing, we found that loading a single account typically requires dozens to hundreds of disk accesses. Even more critically, this delays the execution of individual transactions, which is one reason why Parallel EVM can effectively utilize multi-core capabilities and improve throughput.

Problem 2: Hash-Based Addressing:

MPT and IAVL’s Merklized State Data typically use hash-based addressing. While this method efficiently manages multi-version and verifiable state data, it also results in high I/O bandwidth and read amplification, leading to increased system resource consumption (e.g., during compaction). This is one reason why the performance of many parallel EVMs differs significantly between small test data sets and real blockchain environments. Additionally, this model is not well-suited to pruning and other data management operations.

Problem 3: State Bloat:

As the number of users and transaction volume accumulates, the space occupied by the world state also increases. Since the memory of Validators is often limited, cache hit rates continue to drop, leading to declining read/write efficiency, further reducing the node’s “parallelism.” In Pharos’ tests, this issue becomes particularly apparent when the number of users reaches the billion level, posing a significant obstacle to the mass adoption of Web3.

As state bloat worsens, the efficiency of starting new nodes continues to decline, further impacting network scale and decentralization.

Why Do We Still Need Multi-Version Verifiable Storage?

To build a decentralized, verifiable, and secure blockchain network, we believes that the current blockchain model must continue to adhere to the principles of authentication and multi-version storage, for the following reasons:

1. Authentication Enhances Finality and Security:

  • For light clients and dApps, quick access to Simple Payment Verification (SPV) enables trusted ledger information to be displayed, preventing malicious nodes from tampering with data.

  • For other nodes within the blockchain network, authentication allows for rapid anchoring of the world state, protecting against malicious nodes spreading fake ledger information, thus enhancing network security.

  • It ensures that transaction records and account states cannot be tampered with, guaranteeing the authenticity and validity of every transaction, thereby increasing user trust in the network.

2. Multi-Version Enhances Reliability and Decentralization:

  • A version-based ledger design is more disk and database-friendly, effectively reducing bandwidth and disk I/O pressure while improving transaction concurrency and throughput.

  • With the authentication feature, multiple full nodes across the network can quickly synchronize with the same world state, improving network robustness and decentralization.

  • For networks that may experience temporary forks, such as Ethereum, multi-version storage allows for quick rollbacks to previous versions, ensuring reliability and reducing the impact of forks on the network.

Pharos believes that authentication and multi-version storage are critical for maintaining the reliability, decentralization, and fast consensus of blockchain networks, particularly in large-scale heterogeneous networks. Without these technologies, networks would face longer consensus delays, lower reliability, and reduced decentralization, making it difficult to meet the demands of decentralized applications at scale in Web3.

Moreover, as database, OS, compiler, and network technologies continue to advance, blockchain systems can significantly improve their scalability without sacrificing decentralization. With the aid of these technologies, blockchain networks can manage and process large-scale data more efficiently, optimizing resource utilization and achieving higher throughput and lower latency.

Conclusion

Pharos Network Snapshots

Welcome to the official snapshot page for Pharos Network. Here you can find regularly updated data snapshots for each network environment — Devnet, Testnet, and Mainnet — to help you quickly synchronize and bootstrap your nodes without performing a full sync from genesis.

Snapshots include the latest database state and can be used for fast setup, disaster recovery, or performance testing.

💡 Notes & Best Practices

  • Snapshots do not contain full block history, only the latest validated state.

  • Archival nodes should still sync from genesis.

  • After applying a snapshot, the node will continue syncing from the latest height.

  • Always ensure your snapshot corresponds to the correct network and version.

⚠️ Always verify the snapshot source and integrity before applying it to your node.\


Testnet Archive Node Snapshot

Testnet Full Node Snapshot (Pruned)

Devnet Snapshot


🛠️ Mainnet Snapshot

Coming Soon


Call EVM From WASM

This guide will walk you through the process of calling EVM contracts from the WASM code e.g., Rust.

Prerequisites

Before you begin, ensure you have the following:

  • Git: Used for code management and obtain examples.

  • Pharos Devnet/Testnet Access: Access to a Pharos node (local or remote) for interacting with the blockchain.

Setup 1: Install WASM Toolchains With Cargo

Install the pharos wasm toolchain plugin using the Cargo tool:

Add the wasm32-unknown-unknown build target to your Rust compiler:

You should now have it available as a Cargo subcommand:

Setup 2: Set Up the Project

Clone the example repo:

Setup 3: Write the Interoperability Contract

  • Create a new file for your interoperability contract:

Write the interoperability Contract:

  • Open src/lib.rs in your favorite text editor and add the following code:

Compile the Smart Contract:

  • Use cargo to compile the contract:

Step 4: Deploy the Interoperability Contract

Troubleshooting

  • Contract Deployment Fails: Ensure you have enough testnet tokens to cover the deployment cost.

  • Interaction Issues: Verify that the contract address and ABI are correct.

  • Insufficient Balance: Ensure your wallet has enough tokens to transfer.

Foundry

Write Your First Transaction

This guide will walk you through the process of sending your first transaction on the Pharos blockchain using three popular libraries: ethers.js, web3.js, and web3.py. By the end of this guide, you will understand how to send a transaction programmatically using these libraries.

Prerequisites

Before you begin, ensure you have the following:

  • Git: Used for code management and obtain examples.

  • Pharos Devnet/Testnet Access: Access to a Pharos node (local or remote) for interacting with the blockchain.

Setup 1: Pick Your Favorite Contract Develop Framework and IDE

Install your preferred contract framework from the below list:

  • ethers.js

  • web3.js

  • web3.py

Setup 2: Set Up the Project

Clone the example repo and add dependencies.

Step 3: Run the Script

Run the script using Node.js:

Key Points

  • Private Key: Never expose your private key in production. Use environment variables or secure storage.

  • Recipient Address: Replace RECIPIENT_ADDRESS with the actual recipient's wallet address.

  • Gas Limit: Ensure you include a sufficient gas limit for the transaction.

Troubleshooting

  • Transaction Fails: Ensure you have enough testnet tokens to cover the transaction fee.

  • Incorrect Network: Double-check that you are connected to the Pharos Testnet.

  • Invalid Address: Verify that the recipient's address is correct.

Conclusion

Now that you’ve sent your first transaction using ethers.js, web3.js, and web3.py.

This guide provides a comprehensive introduction to sending transactions on the Pharos blockchain using three popular libraries. If you encounter any issues, refer to the Troubleshooting section or consult the respective library's documentation. Happy building! 🚀

Solidity

The official Solidity documentation is the most comprehensive and up-to-date resource for learning about the Solidity language. It covers everything from basic syntax to advanced topics and provides detailed explanations, examples, and code snippets.

Learning Resources

Online Tutorials and Courses

  • CryptoZombies: An interactive online course that teaches Solidity through building a zombie game.

  • Dapp University: A YouTube channel with over 10 hours of hands-on tutorials for both beginners and experienced Solidity developers.

  • Udemy Ethereum Blockchain Developer Bootcamp With Solidity: An extensive course providing up-to-date blockchain development tools and resources.

Community and Discussion

  • Ethereum StackExchange: A platform for asking and answering questions related to Solidity and Ethereum development.

  • Solidity Language Users Chat: A chat room for Solidity developers to discuss and share knowledge.

Development Environments and Tools

Integrated Development Environments (IDEs)

  • Remix: A browser-based IDE with an integrated compiler and Solidity runtime environment.

  • Hardhat: An Ethereum development environment with local Ethereum network, debugging features, and a plugin ecosystem.

  • Foundry: A fast, portable, and modular toolkit for Ethereum application development written in Rust.

Editor Integrations

  • Visual Studio Code (VS Code): Solidity extensions for syntax highlighting, compilation, and debugging.

  • IntelliJ IDEA: Solidity plugin for IntelliJ IDEA and other JetBrains IDEs.

Linters and Tools

  • Solhint: A Solidity linter that provides security, style guide, and best practice rules for smart contract validation.

  • Ethlint: A linter to identify and fix style and security issues in Solidity.

Additional Resources

Example Projects

  • Solidity by Example: A collection of example contracts to help you understand Solidity in practice.

Security and Best Practices

  • Security Considerations: A section in the Solidity documentation that provides guidance on security best practices.

Community Translations

The Solidity documentation is available in multiple languages, thanks to community volunteers.

Third-Party Tools and Parsers

  • Solidity Parser for JavaScript: A Solidity parser built on top of ANTLR4 grammar for JavaScript.

  • Sūrya: A utility tool for smart contract systems, offering visual outputs and information about contract structure.

Figure 1: Pharos Store Architecture

2. Disk I/O: Execution and database operations place a significant load on disk I/O. For instance, transaction execution requires loading accounts and storage slots, while merklization involves accessing Trie nodes. Even optimized storage models like and continue to face issues like read and write amplification.

Contract Name
Description
Address
Symbol
Name
initsupply
Decimals
Address

As the number of users and transaction volume increase, the amount of data managed by a single Validator and Full Node continues to grow. For example, as of Nov 2024, Ethereum has nearly (Figure 2), and an Ethereum Full Node requires about (Figure 3) of data synchronization.

In conclusion, truly addressing the blockchain store problem is key to building a large-scale, usable Web3 infrastructure. To this end, Pharos has introduced and implemented the first Blockchain Native Store, as detailed in the .

See for detailed instructions.

Latest Snapshot
snapshot-2025-06-20-10-24.tar.gz
Latest Snapshot
snapshot-2025-06-24-03-17.tar.gz
Latest Snapshot
snapshot-20250426.tar.gz

Rust: Install it from .

Note: Pharos built the chain excution client from scratch using C++, and we design, developed and open-sourced the VM, which combines EVM and WASM in a deeply compiled VM arch with native interoperability. The Rust toolchain and Rust SDK are forked from Stylus toolchain and SDK to facilitate easier adoption, the change here is the removal of Arbitrum ink billing and the simplification of the activation and compilation process on Pharos.

This guide is suitable for developers who want to start building dApps using Pharos and Foundry toolchains. If you are a new user of Ethereum, please consider researching the before continuing.

Link:

Link:

Link:

Link:

Link:

Link:

Link:

Link:

Link:

Link:

Link:

Link:

Link:

Link:

Link:

Chinese (Simplified):

Spanish:

Russian:

Link:

Link:

Create2Deployer

Helper for CREATE2 opcode usage

0x969A0e040a9719a8FAd033a03dCA38542a0ef7DC

DeterministicDeploymentProxy

Integrated with Foundry for deterministic deployments

0xD23e367221077faD8fe332f01f987c36844Fec16

MultiCall3

Allows bundling multiple transactions

0xd579c2FF374fCf31a380f40fc7876Bea959e42e1

GnosisSafe (v1.3.0)

Multisignature wallet

0xd7FC189E465EF477015B0D0e44d0f05F63eBd7f1

GnosisSafeL2 (v1.3.0)

Events-based implementation of GnosisSafe

0x0d97E61437B137D7E1a6171E667D8a4149E07bb5

MultiSendCallOnly (v1.3.0)

Batches multiple transactions (calls only)

0xc94702691320037e69BD8EaD114B81db100e863F

MultiSend (v1.3.0)

Batches multiple transactions

0x6099f88BBe48907e22051F4A38630B603AC3A592

Permit2

Next-generation token approval system

0xe25391e98A161F9f02eA0Ec64dbB047A798b6D17

EntryPoint (v0.7.0)

ERC-4337 entry point for account abstraction

0x5A74dC7aeacC22e325240838eDDcf1A96E9BC5c6

SenderCreator (v0.7.0)

Helper for EntryPoint

0x9fC7AceF4676ed04083F84b0e22332005cf2F2c9

USDC

USD Coin

0

6

0x72df0bcd7276f2dFbAc900D1CE63c272C4BCcCED

USDT

Tether USD

0

6

0xD4071393f8716661958F766DF660033b3d35fD29

WBTC

Wrapped BTC

0

18

0x8275c526d1bCEc59a31d673929d3cE8d108fF5c7

WETH

Wrapped ETH

0

18

0x4E28826d32F1C398DED160DC16Ac6873357d048f

WPHRS

Wrapped PHRS

0

18

0x3019B247381c850ab53Dc0EE53bCe7A07Ea9155f

Last Updated

snapshot-2025-06-20-10-24.tar.gz

Download URL

Download

Format

Compressed TAR archive

Notes

Only includes the public database

sha256 checksum

f3c8c2bfe7fa281da99263c8793375c5bf0df26af2a29d7d6598668a3ceb7ec6

Last Updated

snapshot-2025-06-24-03-17.tar.gz

Download URL

Download

Format

Compressed TAR archive

Notes

Only includes the public database

sha256 checksum

ba85b80db12a422d732d45ccd45dee22021d10bc8d26cfc0ea0bef441f781a66

Last Updated

April 26, 2025

Download URL

Download

Format

Compressed TAR archive

Notes

Only includes the public database

Sha256 checksum

a03bb32dfae5b9930f7681e0054842bdd0e8bba8a3c575a220f1ca8b14d72453

cargo install --git https://github.com/PharosNetwork/pharos-cargo-stylus
rustup target add wasm32-unknown-unknown
cargo stylus --help

Cargo subcommand for developing Pharos Stylus projects
git clone https://github.com/PharosNetwork/examples
cd examples/interoperability/call-evm-from-wasm
touch src/lib.rs
#![cfg_attr(not(feature = "export-abi"), no_main)]
extern crate alloc;

use stylus_sdk::{
    abi::Bytes,
    alloy_primitives::{Address, U256},
    prelude::*,
    stylus_core::calls::context::Call,
};
use alloy_sol_types::{sol, SolCall};

sol! {
    interface IErc20  {
        function mint(uint256 value) external;
    }
}

#[storage]
#[entrypoint]
pub struct Interoperability;

#[public]
impl Interoperability {
    /// Here we can call an EVM contract with the given target address and calldata.
    pub fn execute(&self, target: Address, data: Bytes) -> Bytes {
        let result = self.vm().call(&Call::default(), target, &data);
        result.unwrap().into()
    }

    /// Here we can transfer ETH to the given target address.
    pub fn transfer_eth(&self, to: Address, amount: U256) -> Result<(), Vec<u8>> {
        self.vm().transfer_eth(to, amount)
    }

    /// Here we call an ERC20 token contract written in Solidity.
    pub fn mint_erc20(&self, erc20: Address, value: U256) -> Bytes {
        self.execute(erc20, Bytes(IErc20::mintCall {
            value,
        }.abi_encode()))
    }
}
cargo stylus check --endpoint=<PHAROS_RPC_URL>
cargo stylus deploy --private-key=<YOUR_PRIVATE_KEY> --endpoint=<PHAROS_RPC_URL>
git clone https://github.com/PharosNetwork/examples
cd examples/transaction/ethersjs
npm install
const { ethers } = require("ethers");

// Connect to Pharos Testnet
const provider = new ethers.providers.JsonRpcProvider("<PHAROS_RPC_URL>");

// Note: Your wallet private key (for testnet only, never expose this in production)
const privateKey = "YOUR_PRIVATE_KEY";
const wallet = new ethers.Wallet(privateKey, provider);

// Transaction details
const tx = {
    to: "RECIPIENT_ADDRESS", // Note: Replace with the recipient's address
    value: ethers.utils.parseEther("0.1"), // Amount to send (0.1 PHAR)
};

// Send the transaction
wallet.sendTransaction(tx)
    .then((transaction) => {
        console.log("Transaction sent:", transaction.hash);
    })
    .catch((error) => {
        console.error("Error sending transaction:", error);
    });
node index.js
reth
erigon
290 million addresses
1TB
Pharos Store: The Future of Blockchain Storage
Rapid Node Initialization
rust-lang.org
Dora
Ethereum documentation
Solidity Documentation
CryptoZombies
Dapp University
Udemy Course
Ethereum StackExchange
Solidity Chat
Remix IDE
Hardhat
Foundry
Solidity VS Code Extension
IntelliJ IDEA Solidity Plugin
Solhint
Ethlint
Solidity by Example
Security Considerations
Solidity Documentation (Chinese)
Solidity Documentation (Spanish)
Solidity Documentation (Russian)
Solidity Parser for JavaScript
Sūrya
Figure 1: Time breakdown in Geth Client
Figure 2: Ethereum Unique Address Chart
Figure 3: Ethereum Full Node Sync (Default) Chart
Figure 4: Performance issues in tradition verifiable storage
Figure 5: Compaction in LSM-tree-based key value store

Write Your First Uniswap Contract

This guide will walk you through the process of creating and deploying a simple Uniswap-like decentralized exchange (DEX) contract on the Pharos blockchain. By the end of this guide, you will have a basic understanding of how automated market makers (AMMs) work and how to implement a simple DEX.

Prerequisites

Before you begin, ensure you have the following:

  • Git: Used for code management and obtain examples.

  • Node.js: Install it from nodejs.org.

  • Pharos Devnet/Testnet Access: Access to a Pharos node (local or remote) for interacting with the blockchain.

Setup 1: Install Foundry

  • Foundry

Setup 2: Set Up the Project

Clone the example repo:

git clone https://github.com/PharosNetwork/examples
cd examples/uniswap/foundry/contract

Install OpenZeppelin Contracts:

  • Foundry uses forge to manage dependencies. Install OpenZeppelin contracts:

forge install OpenZeppelin/openzeppelin-contracts --no-git --no-commit

Step 3: Write the Uniswap Contract

Create a New Solidity File:

  • Create a new file for your uniswap contract:

touch src/Uniswap.sol

Write the uniswap Contract:

  • Open src/Uniswap.sol in your favorite text editor and add the following code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";

contract Uniswap {
    address public tokenA;
    address public tokenB;
    uint256 public reserveA;
    uint256 public reserveB;

    constructor(address _tokenA, address _tokenB) {
        tokenA = _tokenA;
        tokenB = _tokenB;
    }

    function addLiquidity(uint256 amountA, uint256 amountB) external {
        require(IERC20(tokenA).transferFrom(msg.sender, address(this), amountA), "Transfer failed");
        require(IERC20(tokenB).transferFrom(msg.sender, address(this), amountB), "Transfer failed");

        reserveA += amountA;
        reserveB += amountB;
    }

    function removeLiquidity(uint256 amountA, uint256 amountB) external {
        require(reserveA >= amountA && reserveB >= amountB, "Insufficient reserves");

        reserveA -= amountA;
        reserveB -= amountB;

        require(IERC20(tokenA).transfer(msg.sender, amountA), "Transfer failed");
        require(IERC20(tokenB).transfer(msg.sender, amountB), "Transfer failed");
    }

    function swapAToB(uint256 amountA) external {
        uint256 amountB = (amountA * reserveB) / reserveA;
        require(IERC20(tokenA).transferFrom(msg.sender, address(this), amountA), "Transfer failed");
        require(IERC20(tokenB).transfer(msg.sender, amountB), "Transfer failed");

        reserveA += amountA;
        reserveB -= amountB;
    }

    function swapBToA(uint256 amountB) external {
        uint256 amountA = (amountB * reserveA) / reserveB;
        require(IERC20(tokenB).transferFrom(msg.sender, address(this), amountB), "Transfer failed");
        require(IERC20(tokenA).transfer(msg.sender, amountA), "Transfer failed");

        reserveB += amountB;
        reserveA -= amountA;
    }
}

Compile the Smart Contract:

  • Use forge to compile the contract:

forge build

Test the Smart Contract

  • Use forge to test the contract:

forge test

Step 4: Deploy the Uniswap Contract

Create a Deployment Script:

  • Create a new file for the deployment script:

touch script/DeployUniswap.s.sol

Write the Deployment Script:

  • Open script/DeployUniswap.s.sol and add the following code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "forge-std/Script.sol";
import "../src/Uniswap.sol";

contract DeployUniswap is Script {
    function run() external {
        uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
        vm.startBroadcast(deployerPrivateKey);

        address tokenA = address(0xAA); // Replace with the address of token A
        address tokenB = address(0xBB); // Replace with the address of token B

        Uniswap uniswap = new Uniswap(tokenA, tokenB);

        vm.stopBroadcast();
    }
}

Set the private key:

export PRIVATE_KEY=<your private key>

Deploy the Contract:

  • Use forge to deploy the contract to the Pharos Testnet:

forge script script/DeployUniswap.s.sol --rpc-url <PHAROS_RPC_URL> --broadcast

Step 5: Interact with the Uniswap Contract

Open script/InteractUniswap.s.sol and add the following code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "forge-std/Script.sol";
import "../src/Uniswap.sol";
import "../test/Uniswap.t.sol";

contract DeployUniswap is Script {
    function run() external {
        uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
        vm.startBroadcast(deployerPrivateKey);

        MockERC20 tokenA = new MockERC20("TokenA", "TKA");
        MockERC20 tokenB = new MockERC20("TokenB", "TKB");

        Uniswap uniswap = new Uniswap(address(tokenA), address(tokenB));

        console.log("TokenA deployed at:", address(tokenA));
        console.log("TokenB deployed at:", address(tokenB));
        console.log("Uniswap deployed at:", address(uniswap));

        vm.stopBroadcast();
    }
}

Execute the script using forge:

forge script script/InteractUniswap.s.sol --rpc-url <PHAROS_RPC_URL> --broadcast

Troubleshooting

  • Contract Deployment Fails: Ensure you have enough testnet tokens to cover the deployment cost.

  • Interaction Issues: Verify that the contract address and ABI are correct.

  • Test Failures: Check the test output for detailed error messages and adjust the tests accordingly.

Conclusion

This guide provides a comprehensive introduction to creating and deploying a Uniswap-like contract on the Pharos blockchain using Foundry. If you encounter any issues, refer to the Foundry documentation or the troubleshooting section. Happy building! 🚀

EVM

The Ethereum Virtual Machine (EVM) is the core component of the Ethereum blockchain, responsible for executing smart contracts and managing the state of the network. It acts as a decentralized computer, maintaining a global state and executing program instructions defined in smart contracts. Key features include:

  • State Machine: Executes transactions and changes the blockchain state.

  • Deterministic Execution: Given the same input, it will always produce the same output.

  • Isolated Execution: Executes code in a sandboxed environment.

References:

  • Ethereum Yellow Paper: The authoritative technical document that defines the EVM and its operational mechanisms.

Learning Resources

Tutorials and Guides

  • EVM Playground: An interactive platform for experimenting with EVM opcodes and bytecode. It provides detailed explanations and visualizations of how EVM executes opcodes.

    • Accessing Constant Variables: Learn how to define and use constant variables in EVM. Link

    • Function Parameters from Calldata: Understand how to access function parameters using calldata. Link

    • Testing Macros in EVM.codes: Build and test functions using raw EVM bytecode. Link

    • General EVM Playground: Link

EVM Cheatsheet: A comprehensive guide detailing EVM architecture, functionalities, and operational mechanisms. It covers:

  • EVM Architecture: Stack, memory, storage, and instruction set.

  • Bytecode and Opcodes: Detailed explanations of EVM bytecode and commonly used opcodes.

  • Memory vs. Storage: Differences and use cases.

  • Gas and Gas Management: Understanding gas costs and optimization techniques.

  • Link: EVM Cheatsheet

Academic Research

  • Smart Contract Decompilation: Learn how to decompile EVM bytecode back into high-level languages like Solidity. Tools like Mythril, Ethersplay, or Porosity are used for this purpose.

    • Mythril: Link

    • Ethersplay: Link

    • Porosity: Link

  • EVM Execution Model: Explore how EVM executes opcodes, manages memory and storage, and handles transactions.

    • Link: Ethereum Yellow Paper

Tools for EVM Development

  • EVM From Scratch: A project that guides you through implementing your own EVM in various programming languages. It helps in understanding the core mechanics of EVM.

    • Link: EVM From Scratch

  • EVM Puzzles: A collection of interactive puzzles designed to help you practice and understand EVM operations.

    • Link: EVM Puzzles

Community and Discussion

  • EVM Learning Manual: A curated list of resources for learning EVM, maintained by the blockchain community.

    • Link: EVM Learning Manual

  • Stack Overflow: A platform where you can find answers to common EVM-related questions and participate in discussions.

    • Link: Stack Overflow - EVM Tag

Practical Examples and Use Cases

  • Contract Address Generation: Learn how contract addresses are generated using sender address and nonce.

    • Link: Contract Address Generation

  • Bytecode Decompilation: Understand the process of converting bytecode into opcodes and reconstructing high-level code.

    • Link: Mythril Documentation

  • Storage Management: Explore how EVM handles storage variables, including writing to and reading from storage slots.

    • Link: Solidity Documentation - Storage

References

  • EVM Playground: https://evm.codes

  • EVM Cheatsheet: https://github.com/pylaugh/evm-cheatsheet

  • EVM From Scratch: https://github.com/w1nt3r-eth/evm-from-scratch

  • EVM Puzzles: https://github.com/fvictorio/evm-puzzles

  • EVM Learning Manual: https://learnblockchain.cn/article/4800

  • Stack Overflow - EVM Tag: https://stackoverflow.com/questions/tagged/evm

  • Contract Address Generation: https://ethereum.stackexchange.com/questions/760/how-is-the-address-of-an-ethereum-contract-computed

  • Mythril Documentation: https://mythril.readthedocs.io/en/latest/

  • Solidity Documentation - Storage: https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html

Write Your First NFT

Prerequisites

Before you begin, ensure you have the following:

  • Git: Used for code management and obtain examples.

  • Node.js: Install it from nodejs.org.

  • Pharos Devnet/Testnet Access: Access to a Pharos node (local or remote) for interacting with the blockchain.

Setup 1: Install Hardhat

  • Hardhat

Setup 2: Set Up the Project

Clone the example repo:

git clone https://github.com/PharosNetwork/examples
cd examples/nft/hardhat/contract

Install OpenZeppelin Contracts:

npm install

Setup 3: Write the NFT Contract

Create a New Solidity File:

  • Create a new file for your NFT contract:

touch contracts/Token.sol

Write the Token Contract:

  • Open contracts/Token.sol in your favorite text editor and add the following code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";

contract Token is ERC721 {
    uint256 id;
    constructor() ERC721("Token", "MTK") {}

    function mint(address to) public returns (uint256) {
        id += 1;
        _mint(to, id);
        return id;
    }
}

Compile the Smart Contract:

npx hardhat compile

Test the Smart Contract

npx hardhat test

Step 4: Deploy the Token Contract

Set the private key:

npx hardhat vars set PRIVATE_KEY

Deploy the Contract:

npx hardhat ignition deploy ./ignition/modules/Token.js --network pharos

Step 5: Verify the Token Contract

Add the following content to your hardhat.config.js file

Field
Value

chain_name

pharos

chain_id

688688

rpc_endpoint

https://testnet.dplabs-internal.com

api_host

https://api.socialscan.io/pharos-testnet/v1/explorer/command_api/contract

explorer_url

https://testnet.pharosscan.xyz/

require("@nomicfoundation/hardhat-toolbox");

/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
  solidity: "0.8.28",
  networks: {
    pharos: {
      url: "https://testnet.dplabs-internal.com",
      accounts: [vars.get("PRIVATE_KEY")],
    },
  },
  etherscan: {
    customChains: [
      {
        network: "pharos",
        chainId: 688688,
        urls: {
          apiURL: "https://api.socialscan.io/pharos-testnet/v1/explorer/command_api/contract",
          browserURL: "https://testnet.pharosscan.xyz/",
        },
      },
    ],
    apiKey: {
      pharos: "Put a random string", // Note we don't need a apiKey here, just leave a random string
    },
  }
};

Run the hardhat verify command

npx hardhat verify --network pharos <contract_address> <constructor_args_params>

Troubleshooting

  • Contract Deployment Fails: Ensure you have enough testnet tokens to cover the deployment cost.

  • Interaction Issues: Verify that the contract address and ABI are correct.

  • Insufficient Balance: Ensure your wallet has enough tokens to transfer.

Conclusion

Now that you’ve created and deployed your first NFT using Hardhat.

This guide provides a comprehensive introduction to to creating and deploying an NFT on the Pharos blockchain. If you encounter any issues, refer to the Troubleshooting section or consult the Hardhat documentation. Happy building! 🚀

Write Your First Token

This guide will walk you through the process of creating and deploying your first token on the Pharos blockchain. By the end of this guide, you will have a fully functional token contract and understand how to interact with it.

Prerequisites

Before you begin, ensure you have the following:

  • Git: Used for code management and obtain examples.

  • Node.js: Install it from nodejs.org.

  • Pharos Devnet/Testnet Access: Access to a Pharos node (local or remote) for interacting with the blockchain.

Setup 1: Install Hardhat

  • Hardhat

Setup 2: Set Up the Project

Clone the example repo:

git clone https://github.com/PharosNetwork/examples
cd examples/token/hardhat/contract

Install OpenZeppelin Contracts:

npm install

Setup 3: Write the Token Contract

Create a New Solidity File:

  • Create a new file for your token contract:

touch contracts/Token.sol

Write the Token Contract:

  • Open contracts/Token.sol in your favorite text editor and add the following code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract Token is ERC20 {
    constructor(uint256 initialSupply) ERC20("Token", "MTK") {
        _mint(msg.sender, initialSupply);
    }
}

Compile the Smart Contract:

npx hardhat compile

Test the Smart Contract

npx hardhat test

Step 4: Deploy the Token Contract

Set the private key:

npx hardhat vars set PRIVATE_KEY

Deploy the Contract:

npx hardhat ignition deploy ./ignition/modules/Token.js --network pharos

Step 5: Verify the Token Contract

Add the following content to your hardhat.config.js file

Field
Value

chain_name

pharos

chain_id

688688

rpc_endpoint

https://testnet.dplabs-internal.com

api_host

https://api.socialscan.io/pharos-testnet/v1/explorer/command_api/contract

explorer_url

https://testnet.pharosscan.xyz/

require("@nomicfoundation/hardhat-toolbox");

/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
  solidity: "0.8.28",
  networks: {
    pharos: {
      url: "https://testnet.dplabs-internal.com",
      accounts: [vars.get("PRIVATE_KEY")],
    },
  },
  etherscan: {
    customChains: [
      {
        network: "pharos",
        chainId: 688688,
        urls: {
          apiURL: "https://api.socialscan.io/pharos-testnet/v1/explorer/command_api/contract",
          browserURL: "https://testnet.pharosscan.xyz/",
        },
      },
    ],
    apiKey: {
      pharos: "Put a random string", // Note we don't need a apiKey here, just leave a random string
    },
  }
};

Run the hardhat verify command

npx hardhat verify --network pharos <contract_address> <constructor_args_params>

Troubleshooting

  • Contract Deployment Fails: Ensure you have enough testnet tokens to cover the deployment cost.

  • Interaction Issues: Verify that the contract address and ABI are correct.

  • Insufficient Balance: Ensure your wallet has enough tokens to transfer.

Conclusion

Now that you’ve created and deployed your first token using Hardhat.

This guide provides a comprehensive introduction to creating and deploying a token on the Pharos blockchain using Hardhat. If you encounter any issues, refer to the Troubleshooting section or consult the Hardhat documentation. Happy building! 🚀

Write Your First NFT

Prerequisites

Before you begin, ensure you have the following:

  • Git: Used for code management and obtain examples.

  • Node.js: Install it from nodejs.org.

  • Pharos Devnet/Testnet Access: Access to a Pharos node (local or remote) for interacting with the blockchain.

Setup 1: Install Foundry

  • Foundry

Setup 2: Set Up the Project

Clone the example repo:

git clone https://github.com/PharosNetwork/examples
cd examples/nft/foundry/contract

Install OpenZeppelin Contracts:

  • Foundry uses forge to manage dependencies. Install OpenZeppelin contracts:

forge install OpenZeppelin/openzeppelin-contracts --no-git --no-commit

Setup 3: Write the NFT Contract

Create a New Solidity File:

  • Create a new file for your NFT contract:

touch src/Token.sol

Write the Token Contract:

  • Open src/Token.sol in your favorite text editor and add the following code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {ERC721} from "openzeppelin-contracts/contracts/token/ERC721/ERC721.sol";

contract Token is ERC721 {
    constructor() ERC721("Token", "MTK") {}
}

Compile the Smart Contract:

  • Use forge to compile the contract:

forge build

Test the Smart Contract

  • Use forge to test the contract:

forge test

Step 4: Deploy the Token Contract

Set the private key:

export PRIVATE_KEY=<your private key>

Create a Deployment Script:

  • Create a new file for the deployment script:

touch script/DeployToken.s.sol

Write the Deployment Script:

  • Open script/DeployToken.s.sol and add the following code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "forge-std/Script.sol";
import "../src/Token.sol";

contract DeployToken is Script {
    function run() external {
        uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
        vm.startBroadcast(deployerPrivateKey);

        Token token = new Token(1000000); // Initial supply of 1,000,000 tokens

        vm.stopBroadcast();
    }
}

Deploy the Contract:

  • Use forge to deploy the contract to the Pharos Testnet:

forge script script/DeployToken.s.sol --rpc-url <PHAROS_RPC_URL> --broadcast

Step 5: Verify the Token Contract

forge verify-contract \
<contract_address> \
--constructor-args <abi_encoded_args> \
src/Token.sol:Token \
--chain-id 688688 \
--verifier blockscout \
--verifier-url https://api.socialscan.io/pharos-testnet/v1/explorer/command_api/contract

Note: Replace with your token contract address

Step 6: Interact with the NFT Contract

Open script/InteractToken.s.sol and add the following code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import {Script, console} from "forge-std/Script.sol";
import {Token} from "../src/Token.sol";

contract InteractToken is Script {
    function run() external {
        uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
        vm.startBroadcast(deployerPrivateKey);

        Token token = Token(address(0x00)); // Replace with your token contract address

        // Check balance
        uint256 balance = token.balanceOf(msg.sender);
        console.log("Balance:", balance);

        // Transfer tokens
        token.transfer(address(0x00), 100); // Replace with recipient address and amount
        console.log("Tokens transferred");

        vm.stopBroadcast();
    }
}

Execute the script using forge:

forge script script/InteractToken.s.sol --rpc-url <PHAROS_RPC_URL> --broadcast

Troubleshooting

  • Contract Deployment Fails: Ensure you have enough testnet tokens to cover the deployment cost.

  • Interaction Issues: Verify that the contract address and ABI are correct.

  • Insufficient Balance: Ensure your wallet has enough tokens to transfer.

Conclusion

Now that you’ve created and deployed your first NFT using Foundry.

This guide provides a comprehensive introduction to to creating and deploying an NFT on the Pharos blockchain. If you encounter any issues, refer to the Troubleshooting section or consult the Foundry documentation. Happy building! 🚀

Write Your First dApp

This guide will walk you through the process of building and deploying your first end-to-end decentralized application (dApp) on the Pharos blockchain. By the end of this guide, you will have a fully functional dApp that includes a smart contract, a backend, and a frontend.

Prerequisites

Before you begin, ensure you have the following:

  • Git: Used for code management and obtain examples.

  • Node.js: Install it from nodejs.org.

  • Pharos Devnet/Testnet Access: Access to a Pharos node (local or remote) for interacting with the blockchain.

Setup 1: Install Hardhat

  • Hardhat

Setup 2: Set Up the Project

Clone the example repo:

git clone https://github.com/PharosNetwork/examples
cd examples/dapp/hardhat
npm install

Setup 3: Deploy the Smart Contract

Set the private key:

npx hardhat vars set PRIVATE_KEY

Then

cd contract && npm install
npx hardhat ignition deploy ./ignition/modules/Counter.js --network pharos

Setup 4: Build the Frontend

Connect the Frontend to the Smart Contract:

  • Open src/app.jsx and replace its content with the following code:

import React, { useState } from "react";
import { ethers } from "ethers";

const contractAddress = "YOUR_CONTRACT_ADDRESS"; // Replace with your contract address
const abi = [
    {
        "inputs": [],
        "name": "get",
        "outputs": [
            {
                "internalType": "uint256",
                "name": "",
                "type": "uint256"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "uint256",
                "name": "x",
                "type": "uint256"
            }
        ],
        "name": "set",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    }
];

function App() {
    const [value, setValue] = useState("");
    const [storedValue, setStoredValue] = useState("");

    const provider = new ethers.providers.Web3Provider(window.ethereum);
    const signer = provider.getSigner();
    const contract = new ethers.Contract(contractAddress, abi, signer);

    const handleSet = async () => {
        await contract.set(value);
        alert("Value set!");
    };

    const handleGet = async () => {
        const result = await contract.get();
        setStoredValue(result.toString());
    };

    return (
        <div>
            <h1>Simple Storage dApp</h1>
            <input
                type="text"
                value={value}
                onChange={(e) => setValue(e.target.value)}
                placeholder="Enter a value"
            />
            <button onClick={handleSet}>Set Value</button>
            <button onClick={handleGet}>Get Value</button>
            <p>Stored Value: {storedValue}</p>
        </div>
    );
}

export default App;

Replace Placeholder Values

  • Replace YOUR_CONTRACT_ADDRESS with the address of your deployed contract.

Step 5: Run the dApp

Start the React App

  • Navigate to the frontend directory and start the app:

npm start

Interact with the dApp:

  • Open your browser and navigate to http://localhost:3000.

  • Use the input field and buttons to interact with your smart contract.

Troubleshooting

  • Contract Deployment Fails: Ensure you have enough testnet tokens to cover the deployment cost.

  • Frontend Connection Issues: Verify that the contract address and ABI are correct.

Conclusion

Now that you’ve built your first end-to-end dApp.

This guide provides a comprehensive introduction to building and deploying an end-to-end dApp on the Pharos blockchain. If you encounter any issues, refer to the Troubleshooting section or consult the Pharos documentation. Happy building! 🚀

Write Your First Token

This guide will walk you through the process of creating and deploying your first token on the Pharos blockchain. By the end of this guide, you will have a fully functional token contract and understand how to interact with it.

Prerequisites

Before you begin, ensure you have the following:

  • Git: Used for code management and obtain examples.

  • Node.js: Install it from nodejs.org.

  • Pharos Devnet/Testnet Access: Access to a Pharos node (local or remote) for interacting with the blockchain.

Setup 1: Install Foundry

  • Foundry

Setup 2: Set Up the Project

Clone the example repo:

git clone https://github.com/PharosNetwork/examples
cd examples/token/foundry/contract

Install OpenZeppelin Contracts:

  • Foundry uses forge to manage dependencies. Install OpenZeppelin contracts:

forge install OpenZeppelin/openzeppelin-contracts --no-git --no-commit

Setup 3: Write the Token Contract

Create a New Solidity File:

  • Create a new file for your token contract:

touch src/Token.sol

Write the Token Contract:

  • Open src/Token.sol in your favorite text editor and add the following code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";

contract Token is ERC20 {
    constructor(uint256 initialSupply) ERC20("Token", "MTK") {
        _mint(msg.sender, initialSupply);
    }
}

Compile the Smart Contract:

  • Use forge to compile the contract:

forge build

Test the Smart Contract

  • Use forge to test the contract:

forge test

Step 4: Deploy the Token Contract

Create a Deployment Script:

  • Create a new file for the deployment script:

touch script/DeployToken.s.sol

Write the Deployment Script:

  • Open script/DeployToken.s.sol and add the following code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "forge-std/Script.sol";
import "../src/Token.sol";

contract DeployToken is Script {
    function run() external {
        uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
        vm.startBroadcast(deployerPrivateKey);

        Token token = new Token(1000000); // Initial supply of 1,000,000 tokens

        vm.stopBroadcast();
    }
}

Set the private key:

export PRIVATE_KEY=<your private key>

Deploy the Contract:

  • Use forge to deploy the contract to the Pharos Testnet:

forge script script/DeployToken.s.sol --rpc-url <PHAROS_RPC_URL> --broadcast

Step 5: Verify the Token Contract

forge verify-contract \
<contract_address> \
--constructor-args <abi_encoded_args> \
src/Token.sol:Token \
--chain-id 688688 \
--verifier blockscout \
--verifier-url https://api.socialscan.io/pharos-testnet/v1/explorer/command_api/contract

Note: Replace with your token contract address

Step 6: Interact with the Token Contract

Open script/InteractToken.s.sol and add the following code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import {Script, console} from "forge-std/Script.sol";
import {Token} from "../src/Token.sol";

contract InteractToken is Script {
    function run() external {
        uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
        vm.startBroadcast(deployerPrivateKey);

        Token token = Token(address(0x00)); // Replace with your token contract address

        // Check balance
        uint256 balance = token.balanceOf(msg.sender);
        console.log("Balance:", balance);

        // Transfer tokens
        token.transfer(address(0x00), 100); // Replace with recipient address and amount
        console.log("Tokens transferred");

        vm.stopBroadcast();
    }
}

Execute the script using forge:

forge script script/InteractToken.s.sol --rpc-url <PHAROS_RPC_URL> --broadcast

Troubleshooting

  • Contract Deployment Fails: Ensure you have enough testnet tokens to cover the deployment cost.

  • Interaction Issues: Verify that the contract address and ABI are correct.

  • Insufficient Balance: Ensure your wallet has enough tokens to transfer.

Next Steps

Now that you’ve created and deployed your first token using Foundry.

This guide provides a comprehensive introduction to creating and deploying a token on the Pharos blockchain using Foundry. If you encounter any issues, refer to the Troubleshooting section or consult the Foundry documentation. Happy building! 🚀

Write Your First dApp

This guide will walk you through the process of building and deploying your first end-to-end decentralized application (dApp) on the Pharos blockchain. By the end of this guide, you will have a fully functional dApp that includes a smart contract, a backend, and a frontend.

Prerequisites

Before you begin, ensure you have the following:

  • Git: Used for code management and obtain examples.

  • Node.js: Install it from nodejs.org.

  • Pharos Devnet/Testnet Access: Access to a Pharos node (local or remote) for interacting with the blockchain.

Setup 1: Install Foundry

  • Foundry

Setup 2: Set Up the Project

Clone the example repo:

git clone https://github.com/PharosNetwork/examples
cd examples/dapp/foundry
npm install

Setup 3: Deploy the Smart Contract

Set the private key:

export PRIVATE_KEY=<your private key>

Then

cd contract
forge install OpenZeppelin/openzeppelin-contracts --no-git --no-commit
forge script script/Counter.s.sol:CounterScript --rpc-url <PHAROS_RPC_URL> --broadcast

Setup 4: Build the Frontend

Connect the Frontend to the Smart Contract:

  • Open src/app.jsx and replace its content with the following code:

import React, { useState } from "react";
import { ethers } from "ethers";

const contractAddress = "YOUR_CONTRACT_ADDRESS"; // Replace with your contract address
const abi = [
    {
        "inputs": [],
        "name": "get",
        "outputs": [
            {
                "internalType": "uint256",
                "name": "",
                "type": "uint256"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "uint256",
                "name": "x",
                "type": "uint256"
            }
        ],
        "name": "set",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    }
];

function App() {
    const [value, setValue] = useState("");
    const [storedValue, setStoredValue] = useState("");

    const provider = new ethers.providers.Web3Provider(window.ethereum);
    const signer = provider.getSigner();
    const contract = new ethers.Contract(contractAddress, abi, signer);

    const handleSet = async () => {
        await contract.set(value);
        alert("Value set!");
    };

    const handleGet = async () => {
        const result = await contract.get();
        setStoredValue(result.toString());
    };

    return (
        <div>
            <h1>Simple Storage dApp</h1>
            <input
                type="text"
                value={value}
                onChange={(e) => setValue(e.target.value)}
                placeholder="Enter a value"
            />
            <button onClick={handleSet}>Set Value</button>
            <button onClick={handleGet}>Get Value</button>
            <p>Stored Value: {storedValue}</p>
        </div>
    );
}

export default App;

Replace Placeholder Values

  • Replace YOUR_CONTRACT_ADDRESS with the address of your deployed contract.

Step 5: Run the dApp

Start the React App

  • Navigate to the frontend directory and start the app:

npm start

Interact with the dApp:

  • Open your browser and navigate to http://localhost:3000.

  • Use the input field and buttons to interact with your smart contract.

Troubleshooting

  • Contract Deployment Fails: Ensure you have enough testnet tokens to cover the deployment cost.

  • Frontend Connection Issues: Verify that the contract address and ABI are correct.

Conclusion

Now that you’ve built your first end-to-end dApp.

This guide provides a comprehensive introduction to building and deploying an end-to-end dApp on the Pharos blockchain. If you encounter any issues, refer to the Troubleshooting section or consult the Pharos documentation. Happy building! 🚀

Using Docker (Testnet)

Prerequisites

Before starting, ensure that you meet the system requirements for Pharos nodes. Additionally, install the following dependencies:

  • Docker-compose

Pharos Validator Node Deployment Steps

1. Create a working directory for your Pharos node:

docker stop pharos-testnet && docker rm pharos-testnet
export WORKSPACE=testnet
# If you want to keep the existing snapshot, please save the public database first.
mv /data/$WORKSPACE/pharos-node/domain/light/data/public/ /data/
rm -rf /data/$WORKSPACE
mkdir -p /data/$WORKSPACE
cd /data/$WORKSPACE

You need to modify /data/$WORKSPACE and create the $WORKSPACE directory in a data disk with large space. For example, if your data disk is mounted in /app, then mkdir /app/$WORKSPACE

Generate a docker-compose.yml file for managing Pharos nodes

version: '3'

services:
  pharos:
    image: public.ecr.aws/k2g7b7g1/pharos/testnet:rpc_community_0626
    container_name: pharos-testnet
    volumes:
      - /data/$WORKSPACE:/data
    ports:
      - "18100:18100"
      - "18200:18200"
      - "19000:19000"
    restart: unless-stopped

Parameter Explanation

  • name pharos-testnet: Container name, customizable.

  • /data/$WORKSPACE:/data: Local mount directory, recommended to be set on a high-capacity disk.

public.ecr.aws/k2g7b7g1/pharos/testnet:xxxxxxxx: Pharos testnet image address.

In your mount directory there should be a list of files:

  • deploy.light.json: Pharos binary configuration template

  • domain.json: Pharos deployment configuration file

  • genesis.conf: The genesis config of the testnet you are connecting to

And the following directories:

  • pharos-node: Pharos deployment directory, Contains configuration files, binaries, logs, DB, etc.

  • pharos-node-client : Pharos client directory, used to do node management

  • resources : Node's keys directory, including consensus signing key and BLS key. Keep it safe

2. Start the Pharos node and run the following command in the $WORKSPACE directory:

docker-compose up -d (or `docker compose up` depends on your version)

3.⏳ Wait for Sync

Once the local node starts syncing and you can confirm block height is increasing (this may take up to 3 minutes — do not run docker stop or docker-compose down during this period):

curl 127.0.0.1:18100/ \
  -X POST \
  -H "Content-Type: application/json" \
  --data '{"method":"eth_blockNumber","params":[],"id":1,"jsonrpc":"2.0"}'

Optional Steps

If you want to restore the public data:

docker stop pharos-testnet
rm -rf /data/$WORKSPACE/pharos-node/domain/light/data/public/
mv /data/public /data/$WORKSPACE/pharos-node/domain/light/data/
docker-compose up -d

Other commands:

# Stop
docker-compose stop
# Restart
docker-compose restart
# Update to latest version
docker-compose pull
docker-compose down && docker-compose up -d

Write Your First Uniswap Contract

This guide will walk you through the process of creating and deploying a simple Uniswap-like decentralized exchange (DEX) contract on the Pharos blockchain. By the end of this guide, you will have a basic understanding of how automated market makers (AMMs) work and how to implement a simple DEX.

Prerequisites

Before you begin, ensure you have the following:

  • Git: Used for code management and obtain examples.

  • Node.js: Install it from nodejs.org.

  • Pharos Devnet/Testnet Access: Access to a Pharos node (local or remote) for interacting with the blockchain.

Setup 1: Install Hardhat

  • Hardhat

Setup 2: Set Up the Project

Clone the example repo:

git clone https://github.com/PharosNetwork/examples
cd examples/uniswap/hardhat/contract

Install OpenZeppelin Contracts:

npm install

Step 3: Write the Uniswap Contract

Create a New Solidity File:

  • Create a new file for your uniswap contract:

touch contracts/Uniswap.sol

Write the uniswap Contract:

  • Open contracts/Uniswap.sol in your favorite text editor and add the following code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract Uniswap {
    address public tokenA;
    address public tokenB;
    uint256 public reserveA;
    uint256 public reserveB;

    constructor(address _tokenA, address _tokenB) {
        tokenA = _tokenA;
        tokenB = _tokenB;
    }

    function addLiquidity(uint256 amountA, uint256 amountB) external {
        require(IERC20(tokenA).transferFrom(msg.sender, address(this), amountA), "Transfer failed");
        require(IERC20(tokenB).transferFrom(msg.sender, address(this), amountB), "Transfer failed");

        reserveA += amountA;
        reserveB += amountB;
    }

    function removeLiquidity(uint256 amountA, uint256 amountB) external {
        require(reserveA >= amountA && reserveB >= amountB, "Insufficient reserves");

        reserveA -= amountA;
        reserveB -= amountB;

        require(IERC20(tokenA).transfer(msg.sender, amountA), "Transfer failed");
        require(IERC20(tokenB).transfer(msg.sender, amountB), "Transfer failed");
    }

    function swapAToB(uint256 amountA) external {
        uint256 amountB = (amountA * reserveB) / reserveA;
        require(IERC20(tokenA).transferFrom(msg.sender, address(this), amountA), "Transfer failed");
        require(IERC20(tokenB).transfer(msg.sender, amountB), "Transfer failed");

        reserveA += amountA;
        reserveB -= amountB;
    }

    function swapBToA(uint256 amountB) external {
        uint256 amountA = (amountB * reserveA) / reserveB;
        require(IERC20(tokenB).transferFrom(msg.sender, address(this), amountB), "Transfer failed");
        require(IERC20(tokenA).transfer(msg.sender, amountA), "Transfer failed");

        reserveB += amountB;
        reserveA -= amountA;
    }
}

Compile the Smart Contract:

npx hardhat compile

Test the Smart Contract

npx hardhat test

Step 4: Deploy the Uniswap Contract

Set the private key:

npx hardhat vars set PRIVATE_KEY

Deploy the Contract:

npx hardhat ignition deploy ./ignition/modules/Token.js --network pharos

Troubleshooting

  • Contract Deployment Fails: Ensure you have enough testnet tokens to cover the deployment cost.

  • Interaction Issues: Verify that the contract address and ABI are correct.

  • Test Failures: Check the test output for detailed error messages and adjust the tests accordingly.

Conclusion

This guide provides a comprehensive introduction to creating and deploying a Uniswap-like contract on the Pharos blockchain using Hardhat. If you encounter any issues, refer to the Hardhat documentation or the troubleshooting section. Happy building! 🚀

Pharos SPNs

Special Processing Networks (SPNs): The Future World Computing Model

Overview

Pharos Network supports the deployment of Special Processing Networks (SPNs), specialized, customizable blockchain environments designed for diverse application needs. By choosing a validator within the Pharos Network, users can establish dedicated SPNs, each capable of employing unique protocols for specific use cases, such as AIoT private networks or multi-party privacy-enhancing computations. Lightweight SPNs are designed to support networks requiring access to specialized hardware, like TEE for transaction confidentiality or MEV optimization.

Enhancing Scalability with DP5 and Heterogeneous Computing

Pharos SPNs are designed for optimized scalability and adaptability to diverse computational needs. By supporting specialized data and computational requirements, SPNs seamlessly integrate various blockchain ecosystems and computational resources, ultimately optimizing network performance, reducing costs, and meeting the demands of high-load applications.

Table1: SPNs vs. Traditional Subnets and L2 Solutions

Pharos SPN

Traditional Subnet

L2 Solutions

Performance

High

High

High

Cost

Low

Low

High

Scalability

High

High

Medium

Security

High

Medium

Low - Medium

Management

Managed via Contracts

Managed via Blockchain

Managed via Contracts

Startup Efficiency

Minute-level

Minute-level

Minute to hour-level

Customizable Protocols

Customizable

Customizable

Limited consensus customization

MainNet/PrimaryNet Message Confirmation

Seconds

Seconds

Hours to days

Heterogeneous Computation

Additional support for running ZKML, FHE, MPC, LLM, and other application scenarios

Mainly supports general computation

Typically does not support complex heterogeneous computation scenarios

SPN Architecture

Native Restaking Protocol

CommentGive feedback on the editorWithin the Pharos Network, validators stake P Tokens to secure the Primary Network. Each staked token generates a token certificate, stP, which can be restaked into an SPN for additional rewards, albeit with increased slashing risks. SPNs set their own validator requirements, including the target validator count, soft/hard caps on stP, and specific hardware needs. Upon fulfilling these conditions, the Primary Network automatically initiates the creation of the SPN, which then begins to provide its unique services.CommentGive feedback on the editorRestaking enables validators to dynamically allocate their staked assets to SPNs, enhancing both the network’s liquidity and security. This also improves economic incentives and allows for adaptive resource distribution across the network, balancing demand with performance.CommentGive feedback on the editor

Control and Data flow in SPN

  • SPN Manager: Manages SPN creation, destruction, message communication, and asset transfer, with all transactions immutably recorded on the Primary Network.

  • Core Components:

    • Registry: Responsible for SPN registration and management.

    • Mailbox: Records SPN messages and events.

    • Bridge: Manages asset transfers between SPNs and the Primary Network.

  • SPN Network Hub: Facilitates message and event communication across SPNs and the Primary Network.

  • SPN Adapter: Handles incoming messages and events from the Primary Network, ensuring accurate processing and execution within each SPN.

SPN Interoperability Protocol

Pharos enables seamless communication between SPNs using an efficient Cross-SPN Interoperability Protocol:

  1. Cross-SPN Transaction Initiation: A user initiates a cross-SPN transaction in SPN1, aiming for it to be executed in SPN2’s message queue.

  2. Message Transmission: A Relayer sends the transaction, including proof and block header, to the Primary Network.

  3. Verification and Recording: The Primary Network verifies the transaction and records it in the Mailbox, ensuring the transaction’s authenticity.

  4. Message Execution in SPN2: SPN2 retrieves the message, recording it within its own Mailbox, completing the cross-SPN communication process.

Building the Future Web3 Payment Ecosystem

The Pharos Network envisions a robust Web3 payment ecosystem, supporting advanced use cases like monthly payments and decentralized finance concepts such as PayFi. Through SPNs, Pharos can create specialized networks tailored to these financial innovations, providing flexible blockchain and non-blockchain infrastructures.

Conclusion

Pharos SPNs elevate blockchain capabilities by integrating advanced resource management, interoperability, and security measures to foster digital innovation. Leveraging SPNs and Restaking, Pharos seeks to establish a dynamic, secure, and high-performing blockchain ecosystem that can adapt to the fast-evolving digital landscape.

Pharos Testnet: Rebuild Node with Preserved Node Info

This guide helps you rebuild your Pharos Testnet node while preserving your existing validator identity (node info). This is useful when resetting the database but retaining validator keys and configuration.


1️⃣ Stop and Backup the Existing Node

docker stop pharos-testnet
mv /data/testnet /data/testnet_bak
docker rm pharos-testnet

2️⃣ Start a Fresh Node Container

docker run -d --name pharos-testnet \\
  -v /data/testnet:/data \\
  -p 18100:18100 -p 18200:18200 -p 19000:19000 \\
  public.ecr.aws/k2g7b7g1/pharos/testnet:63b85b6b

3️⃣ ⏳ Wait for Initial Sync (~3 minutes)

Do not run docker stop or docker-compose down during this step.

You can check sync progress using:

curl 127.0.0.1:18100/ \\
  -X POST \\
  -H "Content-Type: application/json" \\
  --data '{"method":"eth_blockNumber","params":[],"id":1,"jsonrpc":"2.0"}'

4️⃣ Stop the Node and Restore Node Identity

docker stop pharos-testnet

Replace new config with the backup node info:

rm -rf /data/testnet/pharos-node/domain/light/data/
rm -rf /data/testnet/pharos-node/domain/light/certs/
rm -rf /data/testnet/resources/

mv /data/testnet_bak/pharos-node/domain/light/data/ /data/testnet/pharos-node/domain/light/data/
mv /data/testnet_bak/pharos-node/domain/light/certs/ /data/testnet/pharos-node/domain/light/certs/
mv /data/testnet_bak/resources/ /data/testnet/resources/

5️⃣ Restart and Finalize

docker start pharos-testnet

Wait ~3 minutes again for sync to resume. You can check status using:

curl 127.0.0.1:18100/ \\
  -X POST \\
  -H "Content-Type: application/json" \\
  --data '{"method":"eth_blockNumber","params":[],"id":1,"jsonrpc":"2.0"}'

6️⃣ Clean Up Backup

rm -rf /data/testnet_bak

Hardhat

This guide is suitable for developers who want to start building dApps using Pharos and hardhat toolchains. If you are a new user of Ethereum, please consider researching the Ethereum documentation before continuing.

Write Your First Transaction

This guide will walk you through the process of sending your first transaction on the Pharos blockchain using three popular libraries: ethers.js, web3.js, and web3.py. By the end of this guide, you will understand how to send a transaction programmatically using these libraries.

Prerequisites

Before you begin, ensure you have the following:

  • Git: Used for code management and obtain examples.

  • Pharos Devnet/Testnet Access: Access to a Pharos node (local or remote) for interacting with the blockchain.

Setup 1: Pick Your Favorite Contract Develop Framework and IDE

Install your preferred contract framework from the below list:

  • ethers.js

  • web3.js

  • web3.py

Setup 2: Set Up the Project

Clone the example repo and add dependencies.

git clone https://github.com/PharosNetwork/examples
cd examples/transaction/ethersjs
npm install
const { ethers } = require("ethers");

// Connect to Pharos Testnet
const provider = new ethers.providers.JsonRpcProvider("<PHAROS_RPC_URL>");

// Note: Your wallet private key (for testnet only, never expose this in production)
const privateKey = "YOUR_PRIVATE_KEY";
const wallet = new ethers.Wallet(privateKey, provider);

// Transaction details
const tx = {
    to: "RECIPIENT_ADDRESS", // Note: Replace with the recipient's address
    value: ethers.utils.parseEther("0.1"), // Amount to send (0.1 PHAR)
};

// Send the transaction
wallet.sendTransaction(tx)
    .then((transaction) => {
        console.log("Transaction sent:", transaction.hash);
    })
    .catch((error) => {
        console.error("Error sending transaction:", error);
    });

Step 3: Run the Script

Run the script using Node.js:

node index.js

Key Points

  • Private Key: Never expose your private key in production. Use environment variables or secure storage.

  • Recipient Address: Replace RECIPIENT_ADDRESS with the actual recipient's wallet address.

  • Gas Limit: Ensure you include a sufficient gas limit for the transaction.

Troubleshooting

  • Transaction Fails: Ensure you have enough testnet tokens to cover the transaction fee.

  • Incorrect Network: Double-check that you are connected to the Pharos Testnet.

  • Invalid Address: Verify that the recipient's address is correct.

Conclusion

Now that you’ve sent your first transaction using ethers.js, web3.js, and web3.py.

This guide provides a comprehensive introduction to sending transactions on the Pharos blockchain using three popular libraries. If you encounter any issues, refer to the Troubleshooting section or consult the respective library's documentation. Happy building! 🚀

Node Debugging & Configuration

Block Sync Verification

You can use the RPC API to check whether the node is actively syncing blocks. If the block number is increasing, the node is catching up to the latest chain height.

curl 127.0.0.1:18100/ \
  -X POST \
  -H "Content-Type: application/json" \
  --data '{"method":"eth_blockNumber","params":[],"id":1,"jsonrpc":"2.0"}'

Check if the Node has joined as a Validator

Query the local NodeID

cat /data/domain.json  | grep "NODE_ID"

Send a transaction to join the Validator

https://pharosscan.xyz/tx/0xf0045f3551f3d70df2ce5a1b2abe51839c3c2cf4a3e487c89ef6e5a006e16b92?tab=state

Check NodeID in Pharos system contract

curl -X POST --data '{
    "jsonrpc": "2.0",
    "method": "eth_call",
    "params": [{
        "to": "0x4100000000000000000000000000000000000000",
        "data": "0x9de70258"
    }, "latest"],
    "id": 1
}' -H "Content-Type: application/json" https://devnet.dplabs-internal.com

Log Inspection

All logs are written to the directory:

cd /data/pharos-node/domain/light/log/

To monitor logs in real-time, use:

tail -f pharos.log

Port Configuration

Ensure that the following ports are open and accessible for proper node operation:

18100 — RPC
18200 — P2P
19000 — Internal services
The yellow part above shows that the NodeID has been added to the Validator collection. We will provide a more visual interface later

Rust

This guide is suitable for developers who want to start building dApps using Pharos and Rust WASM toolchains. If you are a new user of Ethereum, please consider researching the Ethereum documentation before continuing.

This guide will walk you through the process of creating and deploying your first token on the Pharos blockchain using Rust and WASM toolchains. By the end of this guide, you will have a fully functional token contract and understand how to interact with it.

Prerequisites

Before you begin, ensure you have the following:

  • Git: Used for code management and obtain examples.

  • Python: Used to interact with the Pharos network and execute contract testing scripts.

  • Rust: Install it from rust-lang.org.

  • Pharos Devnet/Testnet Access: Access to a Pharos node (local or remote) for interacting with the blockchain.

Setup 1: Install WASM Toolchains With Cargo

Install the pharos wasm toolchain plugin using the Cargo tool:

cargo install --git https://github.com/PharosNetwork/pharos-cargo-stylus

Add the wasm32-unknown-unknown build target to your Rust compiler:

rustup target add wasm32-unknown-unknown

You should now have it available as a Cargo subcommand:

cargo stylus --help

Cargo subcommand for developing Pharos Stylus projects

Note: Pharos built the chain execution client from scratch using C++, and we design, developed and open-sourced the Dora VM, which combines EVM and WASM in a deeply compiled VM arch with native interoperability. The Rust toolchain and Rust SDK are forked from Stylus toolchain and SDK to facilitate easier adoption, the change here is the removal of Arbitrum ink billing and the simplification of the activation and compilation process on Pharos.

Setup 3: Write the Token Contract

  • Create a new file for your token contract:

touch src/lib.rs

Write the Token Contract:

  • Open src/lib.rs in your favorite text editor and add the following code:

// Only run this as a WASM if the export-abi feature is not set.
#![cfg_attr(not(any(feature = "export-abi", test)), no_main)]
extern crate alloc;

// Modules and imports
mod erc20;

use crate::erc20::{Erc20, Erc20Error, Erc20Params};
use alloy_primitives::{Address, U256};
use stylus_sdk::{msg, prelude::*};

/// Immutable definitions
struct StylusTestTokenParams;
impl Erc20Params for StylusTestTokenParams {
    const NAME: &'static str = "StylusTestToken";
    const SYMBOL: &'static str = "STTK";
    const DECIMALS: u8 = 18;
}

// Define the entrypoint as a Solidity storage object. The sol_storage! macro
// will generate Rust-equivalent structs with all fields mapped to Solidity-equivalent
// storage slots and types.
sol_storage! {
    #[entrypoint]
    struct StylusTestToken {
        // Allows erc20 to access StylusTestToken's storage and make calls
        #[borrow]
        Erc20<StylusTestTokenParams> erc20;
    }
}

#[public]
#[inherit(Erc20<StylusTestTokenParams>)]
impl StylusTestToken {
    /// Mints tokens
    pub fn mint(&mut self, value: U256) -> Result<(), Erc20Error> {
        self.erc20.mint(msg::sender(), value)?;
        Ok(())
    }

    /// Mints tokens to another address
    pub fn mint_to(&mut self, to: Address, value: U256) -> Result<(), Erc20Error> {
        self.erc20.mint(to, value)?;
        Ok(())
    }

    /// Burns tokens
    pub fn burn(&mut self, value: U256) -> Result<(), Erc20Error> {
        self.erc20.burn(msg::sender(), value)?;
        Ok(())
    }
}

Compile the Smart Contract:

  • Use cargo to compile the contract:

cargo stylus check --endpoint=<PHAROS_RPC_URL>

Step 4: Deploy the Token Contract

cargo stylus deploy --private-key=<YOUR_PRIVATE_KEY> --endpoint=<PHAROS_RPC_URL>

Step 5: Interact with the Token Contract

Open scripts/main.py and replace your deployed contract address to the variable CONTRACT_ADDRESS:

from web3 import Web3

# Replace Pharos RPC URL
RPC_URL = "<Pharos RPC URL>"
# Note: Replace this address to your contract address
CONTRACT_ADDRESS = Web3.to_checksum_address("0x8ca06d75562be39f645b3b1ead98b15ddfd8c06f")
PRIVATE_KEY = "Replace your private key"

contract_abi = [
    {
        "inputs": [],
        "name": "name",
        "outputs": [{"internalType": "string", "name": "", "type": "string"}],
        "stateMutability": "pure",
        "type": "function",
    },
    {
        "inputs": [],
        "name": "symbol",
        "outputs": [{"internalType": "string", "name": "", "type": "string"}],
        "stateMutability": "pure",
        "type": "function",
    },
    {
        "inputs": [],
        "name": "decimals",
        "outputs": [{"internalType": "uint8", "name": "", "type": "uint8"}],
        "stateMutability": "pure",
        "type": "function",
    },
    {
        "inputs": [],
        "name": "totalSupply",
        "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}],
        "stateMutability": "view",
        "type": "function",
    },
    {
        "inputs": [{"internalType": "address", "name": "owner", "type": "address"}],
        "name": "balanceOf",
        "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}],
        "stateMutability": "view",
        "type": "function",
    },
    {
        "inputs": [{"internalType": "address", "name": "to", "type": "address"}, {"internalType": "uint256", "name": "value", "type": "uint256"}],
        "name": "transfer",
        "outputs": [{"internalType": "bool", "name": "", "type": "bool"}],
        "stateMutability": "nonpayable",
        "type": "function",
    },
    {
        "inputs": [{"internalType": "address", "name": "from", "type": "address"}, {"internalType": "address", "name": "to", "type": "address"}, {"internalType": "uint256", "name": "value", "type": "uint256"}],
        "name": "transferFrom",
        "outputs": [{"internalType": "bool", "name": "", "type": "bool"}],
        "stateMutability": "nonpayable",
        "type": "function",
    },
    {
        "inputs": [{"internalType": "address", "name": "spender", "type": "address"}, {"internalType": "uint256", "name": "value", "type": "uint256"}],
        "name": "approve",
        "outputs": [{"internalType": "bool", "name": "", "type": "bool"}],
        "stateMutability": "nonpayable",
        "type": "function",
    },
    {
        "inputs": [{"internalType": "address", "name": "owner", "type": "address"}, {"internalType": "address", "name": "spender", "type": "address"}],
        "name": "allowance",
        "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}],
        "stateMutability": "view",
        "type": "function",
    },
    {
        "inputs": [{"internalType": "uint256", "name": "value", "type": "uint256"}],
        "name": "mint",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function",
    },
    {
        "inputs": [{"internalType": "address", "name": "to", "type": "address"}, {"internalType": "uint256", "name": "value", "type": "uint256"}],
        "name": "mintTo",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function",
    },
    {
        "inputs": [{"internalType": "uint256", "name": "value", "type": "uint256"}],
        "name": "burn",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function",
    },
]

w3 = Web3(Web3.HTTPProvider(RPC_URL))
print(f"Connected to Ethereum: {w3.is_connected()}")
contract = w3.eth.contract(address=CONTRACT_ADDRESS, abi=contract_abi)
your_address = w3.eth.account.from_key(PRIVATE_KEY).address
print(f"Your Address: {your_address}")
print(f"Your Balance: {contract.functions.balanceOf(your_address).call()}")

Execute the script using python:

python3 -m pip install web3 && python3 scripts/main.py

Troubleshooting

  • Contract Deployment Fails: Ensure you have enough testnet tokens to cover the deployment cost.

  • Interaction Issues: Verify that the contract address and ABI are correct.

  • Insufficient Balance: Ensure your wallet has enough tokens to transfer.

Next Steps

Now that you’ve created and deployed your first token using Rust. This guide provides a comprehensive introduction to creating and deploying a token on the Pharos blockchain using Rust. If you encounter any issues, refer to the Troubleshooting section or consult the Rust documentation. Happy building! 🚀

JSON-RPC API Methods

Pharos Network is a fully EVM-equivalent Layer 1 blockchain, supporting a JSON-RPC interface for seamless blockchain interactions. This RPC API is fully compatible with existing Ethereum JSON-RPC API while also providing richer semantics and enhanced services.

Pharos RPC Methods

ETH Methods

eth_protocolVersion

Returns the current protocol version.

Input: None

Output: String - The protocol version

Example:

{
  "jsonrpc": "2.0",
  "method": "eth_protocolVersion",
  "params": [],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x41"
}

eth_gasPrice

Returns the current gas price in Wei.

Input: None

Output: String - Gas price in Wei

Example:

{
  "jsonrpc": "2.0",
  "method": "eth_gasPrice",
  "params": [],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x09184e72a000"
}

eth_maxPriorityFeePerGas

Get the priority fee needed to be included in a block.

Input: None

Output: String - The hex value of the priority fee needed to be included in a block

Example:

{
  "jsonrpc": "2.0",
  "method": "eth_maxPriorityFeePerGas",
  "params": [],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x0"
}

eth_blockNumber

Returns the number of the most recent block.

Input: None

Output: String - Block number in hexadecimal

Example:

{
  "jsonrpc": "2.0",
  "method": "eth_blockNumber",
  "params": [],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x10d4f"
}

eth_getBlockTransactionCountByHash

Returns the number of transactions in a block specified by its hash.

Input:

  • String - Block hash

Output:

  • String - Number of transactions in the block (hexadecimal format)

Example:

{
  "jsonrpc": "2.0",
  "method": "eth_getBlockTransactionCountByHash",
  "params": ["0x5c3d...a7f5"],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x10"
}

eth_getBlockTransactionCountByNumber

Returns the number of transactions in a block specified by its number.

Input:

  • String - Block number (hexadecimal format)

Output:

  • String - Number of transactions in the block (hexadecimal format)

Example:

{
  "jsonrpc": "2.0",
  "method": "eth_getBlockTransactionCountByNumber",
  "params": ["0xa"],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x8"
}

eth_getBlockByHash

Returns information about a block specified by its hash.

Input:

  • String - Block hash

  • Boolean - Whether to include full transaction objects

Output:

  • Object - Block details

Example:

{
  "jsonrpc": "2.0",
  "method": "eth_getBlockByHash",
  "params": ["0x5c3d...a7f5", true],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "number": "0xa",
    "hash": "0x5c3d...a7f5",
    "transactions": [...]
  }
}

eth_getBlockReceipts

Returns the receipts of all transactions in a block.

Input:

  • String - Block number (hexadecimal format)

Output:

  • Array - List of transaction receipts

Example:

{
  "jsonrpc": "2.0",
  "method": "eth_getBlockReceipts",
  "params": ["0x54f"],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": [
    { "transactionHash": "0xabc...123", "status": "0x1" },
    { "transactionHash": "0xdef...456", "status": "0x1" }
  ]
}

eth_getBlockByNumber

Returns information about a block specified by its number.

Input:

  • String - Block number (hexadecimal format)

  • Boolean - Whether to include full transaction objects

Output:

  • Object - Block details

Example:

{
  "jsonrpc": "2.0",
  "method": "eth_getBlockByNumber",
  "params": ["0xa", true],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "number": "0xa",
    "hash": "0x5c3d...a7f5",
    "transactions": [...]
  }
}

eth_getTransactionByHash

Returns information about a transaction by its hash.

Input:

  • String - Transaction hash

Output:

  • Object - Transaction details

Example:

{
  "jsonrpc": "2.0",
  "method": "eth_getTransactionByHash",
  "params": ["0xabc...123"],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "hash": "0xabc...123",
    "blockNumber": "0xa",
    "from": "0xabc...789",
    "to": "0xdef...456"
  }
}

eth_getBlockTransactionCountByHash

Returns the number of transactions in a block specified by its hash.

Input:

  • String - Block hash

Output:

  • String - Number of transactions in the block (hexadecimal format)

Example:

{
  "jsonrpc": "2.0",
  "method": "eth_getBlockTransactionCountByHash",
  "params": ["0x5c3d...a7f5"],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x10"
}

eth_getTransactionByBlockHashAndIndex

Returns a transaction by block hash and index position.

Input:

  • String - Block hash

  • String - Transaction index (hexadecimal format)

Output:

  • Object - Transaction details

Example:

{
  "jsonrpc": "2.0",
  "method": "eth_getTransactionByBlockHashAndIndex",
  "params": ["0x5c3d...a7f5", "0x0"],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "hash": "0xabc...123",
    "from": "0xabc...789",
    "to": "0xdef...456",
    "value": "0xde0b6b3a7640000"
  }
}

eth_getTransactionByBlockNumberAndIndex

Returns a transaction by block number and index position.

Input:

  • String - Block number (hexadecimal format)

  • String - Transaction index (hexadecimal format)

Output:

  • Object - Transaction details

Example:

{
  "jsonrpc": "2.0",
  "method": "eth_getTransactionByBlockNumberAndIndex",
  "params": ["0xa", "0x0"],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "hash": "0xabc...123",
    "from": "0xabc...789",
    "to": "0xdef...456",
    "value": "0xde0b6b3a7640000"
  }
}

eth_getTransactionReceipt

Returns the receipt of a transaction by transaction hash.

Input:

  • String - Transaction hash

Output:

  • Object - Transaction receipt

Example:

{
  "jsonrpc": "2.0",
  "method": "eth_getTransactionReceipt",
  "params": ["0xabc...123"],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "transactionHash": "0xabc...123",
    "blockNumber": "0xa",
    "status": "0x1"
  }
}

eth_getLogs

Returns logs matching a given filter.

Input:

  • Object - Filter parameters

Output:

  • Array - List of log entries

Example:

{
  "jsonrpc": "2.0",
  "method": "eth_getLogs",
  "params": [{"fromBlock": "0xa", "toBlock": "latest", "address": "0x123...456"}],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": [
    { "address": "0x123...456", "data": "0x..." }
  ]
}

eth_chainId

Returns the chain ID of the current network.

Input: None

Output:

  • String - The chain ID as a hexadecimal string.

Example:

{
  "jsonrpc": "2.0",
  "method": "eth_chainId",
  "params": [],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0xc352"
}

eth_getBalance

Returns the balance of an address at a given block.

Input:

  • String - Address to query.

  • String - Block number or "latest", "earliest", "pending".

Output:

  • String - Balance in wei as a hexadecimal string.

Example:

{
  "jsonrpc": "2.0",
  "method": "eth_getBalance",
  "params": ["0x742d35Cc6634C0532925a3b844Bc454e4438f44e", "latest"],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0xde0b6b3a7640000"
}

eth_getTransactionCount

Returns the number of transactions sent from an address.

Input:

  • String - Address to query.

  • String - Block number or "latest", "earliest", "pending".

Output:

  • String - Number of transactions as a hexadecimal string.

Example:

{
  "jsonrpc": "2.0",
  "method": "eth_getTransactionCount",
  "params": ["0x742d35Cc6634C0532925a3b844Bc454e4438f44e", "latest"],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0xa"
}

eth_getStorageAt

Returns the value from a storage position at a given address.

Input:

  • String - Address of the contract.

  • String - Position in storage.

  • String - Block number or "latest", "earliest", "pending".

Output:

  • String - Storage value as a hexadecimal string.

Example:

{
  "jsonrpc": "2.0",
  "method": "eth_getStorageAt",
  "params": ["0x742d35Cc6634C0532925a3b844Bc454e4438f44e", "0x0", "latest"],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x000000000000000000000000000000000000000000000000000000000000000a"
}

eth_getCode

Returns the contract code of an address.

Input:

  • String - Address to query.

  • String - Block number or "latest", "earliest", "pending".

Output:

  • String - Contract code as a hexadecimal string.

Example:

{
  "jsonrpc": "2.0",
  "method": "eth_getCode",
  "params": ["0x742d35Cc6634C0532925a3b844Bc454e4438f44e", "latest"],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x6080604052348015600f57600080fd5b5060..."
}

eth_sendRawTransaction

Submits a raw transaction to the network.

Input:

  • String - Raw signed transaction data.

Output:

  • String - Transaction hash.

Example:

{
  "jsonrpc": "2.0",
  "method": "eth_sendRawTransaction",
  "params": ["0xf86b80843b9aca0082520894a8d7e4fcf4422f17713da6a5a4740a54b3eb3d4880de0b6b3a76400008025a0..."],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
}

eth_call

Executes a new message call without creating a transaction.

Input:

  • Object - Transaction call object:

    • from: (optional) Address of sender.

    • to: Address of contract.

    • gas: (optional) Gas limit.

    • gasPrice: (optional) Gas price.

    • value: (optional) Amount in wei.

    • data: Call data.

  • String - Block number or "latest", "earliest", "pending".

Output:

  • String - Returned data as a hexadecimal string.

Example:

{
  "jsonrpc": "2.0",
  "method": "eth_call",
  "params": [
    {
      "to": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
      "data": "0x06fdde03"
    },
    "latest"
  ],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x..."
}

eth_estimateGas

Estimates the gas required for a transaction.

Input:

  • Object - Transaction object:

    • from: (optional) Address of sender.

    • to: Address of recipient.

    • gas: (optional) Gas limit.

    • gasPrice: (optional) Gas price.

    • value: (optional) Amount in wei.

    • data: (optional) Call data.

Output:

  • String - Estimated gas as a hexadecimal string.

Example:

{
  "jsonrpc": "2.0",
  "method": "eth_estimateGas",
  "params": [
    {
      "to": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
      "data": "0x06fdde03"
    }
  ],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x5208"
}

eth_feeHistory

Returns a fee history for a given block range.

Input:

  • Number - Block count.

  • String - Newest block (e.g., "latest").

  • Array - Percentiles for priority fees.

Output:

  • Object - Fee history.

Example:

{
  "jsonrpc": "2.0",
  "method": "eth_feeHistory",
  "params": [5, "latest", [10, 50, 90]],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "oldestBlock": "0x5bad55",
    "reward": [["0x1", "0x2", "0x3"]],
    "baseFeePerGas": ["0x4", "0x5", "0x6"],
    "gasUsedRatio": [0.1, 0.5, 0.9]
  }
}

eth_getAccount

Returns information about an account.

Input:

  • String - Address. REQUIRED

  • String - blockReference. REQUIRED

Output:

  • Object - Account details.

Example:

{
  "jsonrpc": "2.0",
  "method": "eth_getAccount",
  "params": ["0x742d35Cc6634C0532925a3b844Bc454e4438f44e", "latest"],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "balance": "0xde0b6b3a7640000",
    "nonce": "0xa",
    "codeHash": "0x...",
    "storageRoot": "0x..."
  }
}

eth_createAccessList (This interface is still under debugging and returns a null value)

Generates an access list for a transaction to be used with EIP-2930.

Input:

Object – A transaction call object, excluding accessList (since it’s what this method generates)

  • from (optional): The sender’s address (20 bytes). If omitted, defaults to the node’s default account.

  • to: The recipient’s address (20 bytes). Typically the destination contract or externally owned account.

  • gas (optional): The maximum amount of gas allowed for execution, expressed as a hexadecimal value.

  • gasPrice (optional): The legacy-style gas price (in wei), specified as a hexadecimal. Only used in transactions that do not follow EIP-1559.

  • maxPriorityFeePerGas (optional): The tip, in wei, the sender is willing to pay per unit of gas above the base fee. Must be paired with maxFeePerGas for EIP-1559-style transactions.

  • maxFeePerGas (optional): The total maximum fee per unit of gas (base + tip), in wei. Must be used alongside maxPriorityFeePerGas.

  • value (optional): The amount of Ether to transfer with the transaction, represented as a hexadecimal string in wei.

  • data (optional): The call data, including the method selector and encoded parameters, following Ethereum’s ABI format.

String – Block identifier (e.g., "latest").

Output:

Object – An object containing the generated access list and estimated gas usageObject – (null value temporary):

  • accessList: An array of access descriptors, each including:

    • address: The account address that the transaction will access.

    • storageKeys: An array of storage slot keys (as hex strings) that may be read or written during execution.

  • gasUsed: A hexadecimal string representing the estimated gas consumption for the transaction if the suggested access list is applied.


Example:

{
  "jsonrpc": "2.0",
  "method": "eth_createAccessList",
  "params": [
    {
      "from": "0x8ee...bee",
      "to": "0x0000000000000000000000000000000000000000",
      "data": "0x60806040..."
    },
    "latest"
  ],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "accessList": [],
    "gasUsed": "0xb880",
  }
}

Ethereum Subscription Methods

eth_subscribe

Subscribes to events.

Input:

  • String - Subscription type ("newHeads", "logs", "newPendingTransactions", "syncing").

  • Object - Optional filter parameters.

Output:

  • String - Subscription ID.

Example:

{
  "jsonrpc": "2.0",
  "method": "eth_subscribe",
  "params": ["newHeads"],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x1234567890abcdef"
}

eth_unsubscribe

Unsubscribes from events.

Input:

  • String - Subscription ID.

Output:

  • Boolean - true if successful.

Example:

{
  "jsonrpc": "2.0",
  "method": "eth_unsubscribe",
  "params": ["0x1234567890abcdef"],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": true
}

Network (NET) Methods

net_version

Returns the network ID.

Input: None

Output:

  • String - Network ID as a hexadecimal string.

Example:

{
  "jsonrpc": "2.0",
  "method": "net_version",
  "params": [],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "50002"
}

Web3 Methods

web3_clientVersion

Returns the client version.

Input: None

Output:

  • String - Client version.

Example:

{
  "jsonrpc": "2.0",
  "method": "web3_clientVersion",
  "params": [],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "portal/1.0.0"
}

Debug Methods

debug_getRawBlock

Returns a raw block.

Input:

  • String - Block number or block hash.

Output:

  • String - Raw block data as a hexadecimal string.

Example:

{
  "jsonrpc": "2.0",
  "method": "debug_getRawBlock",
  "params": ["latest"],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0xf90211a0..."
}

debug_getRawHeader

Returns a raw block header.

Input:

  • String - Block number or block hash.

Output:

  • String - Raw block header data as a hexadecimal string.

Example:

{
  "jsonrpc": "2.0",
  "method": "debug_getRawHeader",
  "params": ["latest"],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0xf901..."
}

debug_getRawReceipts

Returns raw receipts.

Input:

  • String - Block number or block hash.

Output:

  • Array - List of raw receipt objects.

Example:

{
  "jsonrpc": "2.0",
  "method": "debug_getRawReceipts",
  "params": ["latest"],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": ["0xf8438080...", "0xf8438080..."]
}

debug_getRawTransaction

Returns a raw transaction.

Input:

  • String - Transaction hash.

Output:

  • String - Raw transaction data as a hexadecimal string.

Example:

{
  "jsonrpc": "2.0",
  "method": "debug_getRawTransaction",
  "params": ["0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"],
  "id": 1
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0xf86b80843b9aca0082520894a8d7e4fcf4422f17713da6a5a4740a54b3eb3d4880de0b6b3a76400008025a0..."
}