> For the complete documentation index, see [llms.txt](https://docs.pharos.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.pharos.xyz/developer-guide/rust.md).

# 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](https://ethereum.org/en/developers/docs/) 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](https://www.rust-lang.org/tools/install).
* 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:

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

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

```shell
rustup target add wasm32-unknown-unknown
```

You should now have it available as a Cargo subcommand:

```shell
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](https://github.com/dp-labs/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:

```shell
touch src/lib.rs
```

Write the Token Contract:

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

```rust
// 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:

```shell
cargo stylus check --endpoint=<PHAROS_RPC_URL>
```

### Step 4: Deploy the Token Contract

```shell
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`:

```python
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:

```shell
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! 🚀


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.pharos.xyz/developer-guide/rust.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
