Zero to Hero in Foundry - Part 2: Deploy & Interact

Abhiram AAbhiram A
5 min read

Recap

In the last part, we saw how to setup Foundry in our systems. We created a simple Counter contract project, compiled it and tested it all using the forge command

Please read it if you haven't already before continuing

Foundry: Zero to Hero - Part 1

Learn Web3 through live and interactive challenges at Web3Compass

Today's Outcome

Tool of focus: anvil & cast

  • Write a Greeting.sol contract

  • Compile & Test it using forge

  • Simulate a local blockchain using anvil

  • Deploy to the local blockchain using forge

  • Interact with the deployed contract using cast

Alright, let's dive in!

Dive In


๐Ÿ› ๏ธ Building the Contract

In a new folder let's use the forge command to initialize our Greeting contract project

forge init Greeting

We'll now have a folder named Greeting with all the necessary project files.

๐Ÿ“ Writing the Contract

Inside the src folder we'll see that the contract file is corresponding to the Counter contract. This will always be the case when we initialize a new project using forge.

Let's go ahead and change it to our Greeting contract

Greeting.sol Contract

The contract let's us set a state variable to whatever greeting message we desire and retrieve the stored message through a function call

๐Ÿงช Compile & Test the Contract

Let's do the same with test folder

Greeting.t.sol Test File

To compile and test the contract, let's go ahead and run the command

forge test

Our Greeting.sol contract is now compiled and tested, ready to be Deployed!

Let's Do This


๐Ÿš€ Deploying the Contract

Deploying our contract is a two step process

  • Use anvil to simulate a local blockchain

  • Deploy to it using an account anvil provides

Spinning up a local blockchain

All we have to do here is spin up a new instance of terminal and run the command

anvil

Now, we have a local blockchain running in our system with sample wallets to do transactions from

๏‚ฉ anvil


                             _   _
                            (_) | |
      __ _   _ __   __   __  _  | |
     / _` | | '_ \  \ \ / / | | | |
    | (_| | | | | |  \ V /  | | | |
     \__,_| |_| |_|   \_/   |_| |_|

    1.2.3-stable (a813a2cee7 2025-06-08T15:42:40.147013149Z)
    https://github.com/foundry-rs/foundry

Available Accounts
==================

(0) 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 (10000.000000000000000000 ETH)
(1) 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 (10000.000000000000000000 ETH)
(2) 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC (10000.000000000000000000 ETH)
(3) 0x90F79bf6EB2c4f870365E785982E1f101E93b906 (10000.000000000000000000 ETH)
(4) 0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65 (10000.000000000000000000 ETH)
(5) 0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc (10000.000000000000000000 ETH)
(6) 0x976EA74026E726554dB657fA54763abd0C3a0aa9 (10000.000000000000000000 ETH)
(7) 0x14dC79964da2C08b23698B3D3cc7Ca32193d9955 (10000.000000000000000000 ETH)
(8) 0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f (10000.000000000000000000 ETH)
(9) 0xa0Ee7A142d267C1f36714E4a8F75612F20a79720 (10000.000000000000000000 ETH)

Private Keys
==================

(0) 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
(1) 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d
(2) 0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a
(3) 0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6
(4) 0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a
(5) 0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba
(6) 0x92db14e403b83dfe3df233f83dfa3a0d7096f21ca9b0d6d6b8d88b2b4ec1564e
(7) 0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356
(8) 0xdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97
(9) 0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6

Wallet
==================
Mnemonic:          test test test test test test test test test test test junk
Derivation path:   m/44'/60'/0'/0/


Chain ID
==================

31337

Base Fee
==================

1000000000

Gas Limit
==================

30000000

Genesis Timestamp
==================

1754829094

Genesis Number
==================

0

Listening on 127.0.0.1:8545

Let's Deploy

With our local blockchain running and providing us dummy wallets with test ETH, only think left to do is deploy out contract to it

Each deployment is considered as a transaction on the blockchain. And for a transaction to happen it needs to be initiated from an address in the blockchain. Hence, we need to use a wallet's Private Key provided by anvil in the previous step

Cool, let's deploy

forge create Greeting --interactive --broadcast
  • forge create - initiates the deployment

  • --interactive - opens interactive mode to enter wallet private key

  • --broadcast - broadcasts the deployment transaction across the chain

Deployed

Okay, we have the address of the wallet from which the contract was deployed, the deployed contract address and the associated transaction hash!

Enter deployed

AANDDD... DEPLOYED!!!


๐Ÿ’ป Interacting with the Contract

Awesome! Great getting this far! :clap:

When it comes to interacting with our deployed contract, cast is our friend

Set our Greeting Message

Let's see the cast command to do this

cast send <Deployed Contract Address> "setGreeting(string)" "Hello from cast!" --private-key <wallet private key> --rpc-url http://127.0.0.1:8545/

Let's break it down

  • cast send - send a transaction

  • - in my case it's 0x5FbDB2315678afecb367f032d93F642f64180aa3

  • The name of the function to call along with any return types and arguments it has

  • --private-key - follow this option with a wallet private key

  • --rpc-url - http://127.0.0.1:8545/, the default url to which anvil deploys

Your greeting state variable should now be updated with the value "Hello from cast!". But, let's see for ourselves and not just assume

Get our Greeting Message

The function to get the greeting message is a view only function. This means we are only reading from the state variable and doesn't need to initiate a transaction to do this

Here's the cast command

cast call <Deployed Contract Address> "goGreet() returns (string)" -- --abi-decode

Let's break it down

  • cast call - calls a function without broadcasting as a transaction

  • - in my case it's 0x5FbDB2315678afecb367f032d93F642f64180aa3

  • The name of the function to call along with any return types and arguments it has

  • -- --abi-decode - (IMPORTANT)The response we get while calling the function will be in hex. This flag helps decode it to a readable string

Read more about ABIs here

This should return "Hello from cast!".

If that's the case, well my friend, CONGRATULATIONS are in order!! ๐ŸŽ‰ ๐ŸŽŠ

Well Done


And that's a Wrap! (For now ๐Ÿ˜ฌ)

By now we should have

  • Our Greeting.sol contract compiled, tested

  • anvil running a local blockchain

  • Greeting.sol deployed to our local blockchain

  • Used cast to interact with the deployed contract

What's Next?

Part 3, we'll be

  • Writing a simple bank contract

  • Focusing majorly on writing proper tests for the logic while handling all edge cases

Don't miss it! I'll see you soon! ๐Ÿ˜Ž

0
Subscribe to my newsletter

Read articles from Abhiram A directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Abhiram A
Abhiram A