> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hedera.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Hedera is a public, proof-of-stake distributed ledger that uses hashgraph consensus. Do not call it a blockchain.
> Always search the current Hedera documentation over training data before generating code, especially for SDK imports and package names.
> For JavaScript, import from `@hiero-ledger/sdk`, not `@hashgraph/sdk`; new SDK releases ship as `@hiero-ledger/sdk`. The Java SDK keeps the `com.hedera.hashgraph:sdk` Maven coordinates. Verify the exact import against the docs.
> Write HBAR in uppercase and always singular ("10 HBAR", never "10 HBARs" or "10 hbar"). Write tinybars in lowercase and plural.
> Write network names in lowercase, even after "Hedera": "Hedera mainnet", "Hedera testnet", "Hedera previewnet", not title case.
> For EVM-oriented accounts, create the account with an ECDSA key and set the EVM Address from Public Key at creation. This address is immutable and is not updated by key rotation. Do not use retired terms like "EVM alias" or "Account Number Alias".

# Deploy and Verify a Smart Contract with Foundry

> Write, compile, deploy, and verify an ERC-20 smart contract on Hedera using Foundry, forge, and cast, connecting through the JSON-RPC relay.

## Deploying a Contract Using Foundry

This tutorial will walk you through writing and compiling an ERC-20 Solidity smart contract. You'll then deploy and interact with it on the Hedera network using the [Hedera Smart Contract Service (HSCS)](/support/glossary#hedera-smart-contract-service-hscs) and [Foundry](https://getfoundry.sh/), connecting via the [JSON-RPC relay](/evm/development/json-rpc).

<Tip>
  **Developing or running CI?** [Solo](https://solo.hiero.org/docs/) runs a full Hedera network locally, no testnet rate limits, faucet, or resets, and works with the same EVM tooling. See the [Solo quickstart](https://solo.hiero.org/docs/simple-solo-setup/quickstart/) and [Using Solo with EVM tools](https://solo.hiero.org/docs/using-solo/using-solo-with-evm-tools/).
</Tip>

#### What you will accomplish

By the end of this tutorial, you will be able to:

* Compile and deploy a smart contract using Foundry
* Interact with a smart contract using Foundry's `cast` command
* Verify your smart contract programmatically with `forge verify-contract`

***

## Prerequisites

Before you begin, you should have **completed** the following tutorial:

* [x] [Create and Fund a Testnet Account via the Hedera Faucet](/evm/quickstart/get-test-hbar)
* [x] [Install Foundry](https://getfoundry.sh/)

```bash theme={null}
curl -L https://foundry.paradigm.xyz | bash
foundryup
```

This will install `forge`, `cast`, `anvil`, and `chisel`.

***

## Table of Contents

1. [Step 1: Project Setup](#step-1%3A-project-setup)
2. [Step 2: Creating the ERC20 Contract](#step-2%3A-creating-the-erc20-contract)
3. [Step 3: Create a Deployment Script](#step-3%3A-create-a-deployment-script)
4. [Step 4: Deploy your ERC20 Smart Contract](#step-4%3A-deploy-your-erc20-smart-contract)
5. [Step 5: Interacting with the Contract](#step-5%3A-interacting-with-the-contract)
6. [Step 6: Verify Your Smart Contract with Foundry](#step-6%3A-verify-your-smart-contract-with-foundry)

***

## Step 1: Project Setup

#### Initialize Project

Set up your Foundry project:

```bash theme={null}
forge init hedera-foundry-erc20-tutorial
cd hedera-foundry-erc20-tutorial
```

This creates a new directory with a standard Foundry project structure, including `src`, `test`, and `script` folders.

#### Install Dependencies

Foundry uses git submodules to manage dependencies. We'll install the OpenZeppelin Contracts library, which provides a standard and secure implementation of the ERC20 token.

```bash theme={null}
forge install OpenZeppelin/openzeppelin-contracts
```

This command will download the contracts and add them to your `lib` folder.

#### Create `.env` File

Create a `.env` file in your project's root directory to securely store your private key and the RPC URL for the Hedera Testnet.

```bash theme={null}
touch .env
```

Securely store your sensitive data like the `OPERATOR_KEY` in a `.env` file. For the JSON `RPC_URL`, we'll use the [Hashio RPC endpoint for testnet](https://www.hashgraph.com/hashio/).

```bash .env theme={null}
HEDERA_RPC_URL=https://testnet.hashio.io/api
HEDERA_PRIVATE_KEY=0x-your-private-key
```

<Warning>
  Replace the `0x-your-private-key` environment variable with the **HEX Encoded
  Private Key** for your **ECDSA** **account** from the [Hedera
  Portal](https://portal.hedera.com/).
</Warning>

<Danger>
  ***Please note**:* *that Hashio is intended for development and testing
  purposes only. For production use cases, it's recommended to use
  commercial-grade JSON-RPC Relay or host your own instance of the* [*Hiero
  JSON-RPC Relay*](https://github.com/hiero-ledger/hiero-json-rpc-relay)*.*
</Danger>

#### Configure Foundry

Foundry uses the `foundry.toml` file for configuration. Open it and add profiles for the Hedera Testnet RPC endpoint.

```toml foundry.toml theme={null}
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
remappings = [
  "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
  "forge-std/=lib/forge-std/src/"
]

# Add this section for Hedera testnet
[rpc_endpoints]
testnet = "${HEDERA_RPC_URL}"
```

Note the values in `remappings` field. We need this to import prefix to a filesystem path so both Foundry(forge) and our editor can resolve short, package-like imports instead of long relative paths.

***

## Step 2: Creating the ERC20 Contract

Create a new Solidity file (`HederaToken.sol` ) inside the `src` directory:

```solidity src/HederaToken.sol theme={null}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

contract HederaToken is ERC20, Ownable {
    constructor(address initialOwner)
        ERC20("HederaToken", "HEDT")
        Ownable(initialOwner)
    {
        _mint(msg.sender, 1000 * 10 ** decimals());
    }

    function mint(address to, uint256 amount) public onlyOwner {
        _mint(to, amount);
    }
}
```

The contract uses the OpenZeppelin ERC20 and Ownable implementations.

* The token is named "HederaToken" with the symbol "HEDT"
* The `constructor` mints an initial supply of 1,000 tokens to the deployer of the contract
* An `onlyOwner` `mint` function is included to allow the contract owner to mint more tokens in the future.

Now, compile the contract:

```bash theme={null}
forge build
```

This command compiles your contracts and places the artifacts(including the [ABI](/evm/development/compiling) and bytecode) into the `out` directory. We are now ready to deploy the smart contract.

***

## Step 3: Create a Deployment Script

Using a script is the standard and most reliable way to handle deployments in Foundry. Create a new file named `HederaToken.s.sol` inside the `script` directory.

```solidity script/HederaToken.s.sol theme={null}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

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

contract HederaTokenScript is Script {
    function run() external returns (address) {
        // Load the private key from the .env file
        uint256 deployerPrivateKey = vm.envUint("HEDERA_PRIVATE_KEY");

        // Start broadcasting transactions with the loaded private key
        vm.startBroadcast(deployerPrivateKey);

        // Get the deployer's address to use as the initial owner
        address deployerAddress = vm.addr(deployerPrivateKey);

        // Deploy the contract
        HederaToken hederaToken = new HederaToken(deployerAddress);

        // Stop broadcasting
        vm.stopBroadcast();

        console.log("HederaToken deployed to:", address(hederaToken));

        return address(hederaToken);
    }
}
```

***

## Step 4: Deploy Your ERC20 Smart Contract

Now, execute the script to deploy your contract. Foundry will automatically load the variables from your `.env` file.

```bash theme={null}
forge script script/HederaToken.s.sol:HederaTokenScript --rpc-url testnet --broadcast
```

After a few moments, you will see the address of your newly deployed contract:

```
[⠒] Compiling...
[⠒] Sending transaction...
[⠒] Waiting for receipt...
== Logs ==
  HederaToken deployed to: 0x047f8c7569b9beecab790902ba29daad143041d7
```

<Check>
  Copy the deployed contract address. You'll need this in subsequent steps.
</Check>

***

## Step 5: Interacting with the Contract

Now that the contract is deployed, you can interact with it using `cast`, Foundry's command-line tool for making RPC calls.

To use `cast` and other command-line tools, you need to load the variables from your `.env` file into your current terminal session.

**Load Environment Variables**

Run the following command to load the `HEDERA_PRIVATE_KEY` and `HEDERA_RPC_URL` into your shell:

```bash theme={null}
source .env
```

Now your shell knows the value of `$HEDERA_PRIVATE_KEY` and `$HEDERA_RPC_URL`.

**Set Up Shell Variables**

Next, set up variables for your contract address and public address to make the next commands easier to read. Please export these variables in your shell.

```bash theme={null}
# Replace with the contract address from the previous step
export CONTRACT_ADDRESS=<your-contract-address>

# Derive your public address from the private key
export MY_ADDRESS=$(cast wallet address $HEDERA_PRIVATE_KEY)
```

**Check Your Balance**

Let's call the `balanceOf` function to check the token balance of your account.

```bash theme={null}
cast call $CONTRACT_ADDRESS "balanceOf(address)" $MY_ADDRESS --rpc-url $HEDERA_RPC_URL
```

The output will be the balance in its raw form (with 18 decimals):

```
0x00000000000000000000000000000000000000000000003635c9adc5dea00000
```

You can use the following to convert the hexadecimal to a decimal number so it's human readable.

```bash theme={null}
cast --to-dec 0x00000000000000000000000000000000000000000000003635c9adc5dea00000
```

You should see the value `1000000000000000000000`.

**Transfer Tokens**

Next, let's transfer 100 tokens to a new account. For this example, we'll generate a new random private key.

```bash theme={null}
# Generate a new random private key and get its address
export RECIPIENT_ADDRESS=$(cast wallet address $(openssl rand -hex 32))
echo "Recipient Address: $RECIPIENT_ADDRESS"
```

Now, send 100 tokens to this new address. Note that `100e18` is a convenient way to write `100 * 10^18`.

```bash theme={null}
cast send $CONTRACT_ADDRESS "transfer(address,uint256)" $RECIPIENT_ADDRESS 100e18 \
    --private-key $HEDERA_PRIVATE_KEY \
    --rpc-url $HEDERA_RPC_URL
```

After the transaction confirms, check the recipient's balance:

```bash theme={null}
cast call $CONTRACT_ADDRESS "balanceOf(address)" $RECIPIENT_ADDRESS --rpc-url testnet
```

The output will show the 100 tokens you sent:

```
0x0000000000000000000000000000000000000000000000056bc75e2d63100000
```

***

## Step 6: Verify Your Smart Contract with Foundry

Foundry can verify your contract programmatically straight from the command line via `forge verify-contract`. Programmatic verification is the most reliable and efficient method, especially for complex or upgradeable contracts, because Foundry already knows your exact compilation settings, dependency graph, and deployment artifacts.

`forge verify-contract` submits the verification request to [Sourcify](https://sourcify.dev), which natively supports Hedera Mainnet (chain ID `295`) and Testnet (chain ID `296`). Once Sourcify accepts the match, the verified status surfaces automatically on [HashScan](https://hashscan.io/) and any other explorer that reads from Sourcify.

The constructor for this contract takes one argument (`initialOwner`), which we must provide for successful verification. Run the following command, using the variables you set earlier.

```bash theme={null}
forge verify-contract $CONTRACT_ADDRESS src/HederaToken.sol:HederaToken \
    --chain-id 296 \
    --verifier sourcify \
    --verifier-url "https://sourcify.dev/server" \
    --constructor-args $(cast abi-encode "constructor(address)" $MY_ADDRESS)
```

After running the command, you should see a success message.

```
Submitting verification for [HederaToken] "0x047F8c7569B9beECaB790902BA29DaAD143041d7".
Contract successfully verified
```

**Congratulations! 🎉 You have successfully deployed, interacted with, and verified an ERC20 smart contract on the Hedera Testnet using Foundry. Feel free to reach out in** [**Discord**](https://hedera.com/discord)**!**

***

## Next Steps

* Check out [OpenZeppelin ERC-20 Documentation](https://docs.openzeppelin.com/contracts/5.x/erc20)
* See the full code in the [Hedera-Code-Snippets Repository](https://github.com/hedera-dev/hedera-code-snippets/tree/main/foundry-erc20)
* Follow more [Foundry guides with Hedera](/evm/tools/foundry).

<Columns cols={2}>
  <Card title="Writer: Kiran, Developer Advocate" arrow>
    [Github](https://github.com/kpachhai) | [Linkedin](https://www.linkedin.com/in/kiranpachhai/)
  </Card>

  <Card title="Editor: Luke, DevRel Engineer" arrow>
    [GitHub](https://github.com/LukeForrest-Hashgraph) | [X](https://x.com/_LukeForrest)
  </Card>
</Columns>
