CoinsBench

Where blockchain developers share their stories, experiences & ideas.

Follow publication

Foundry Fundamentals Part-1

Foundry Setup

Installing Foundry

curl -L https://foundry.paradigm.xyz | bash

Install Foundry components

foundryup

Create a folder

mkdir foundry-f23
cd foundry-f23

Creating a new project

forge init nameOfNewFolder

We will get these files under foundry-f23

lib is the folder where all your dependencies are installed, here you'll find things like:

  • forge-std (the forge library used for testing and scripting)
  • openzeppelin-contracts is the most battle-tested library of smart contracts
  • and many more, depending on what you need/install

scripts is a folder that houses all your scripts

src is the folder where you put all your smart contracts

test is the folder that houses all your tests

foundry.toml - gives configuration parameters for Foundry

More on these folders and files later.

Please right-click src, click on New File and name it SimpleStorage.sol. Copy the code available here.

One last thing, please delete Counter.s.sol, Counter.sol and Counter.t.sol. These files are a set of basic smart contracts that Foundry provides as a default when you create a new Foundry project.

Deploy a smart contract locally using Anvil

anvil

Deploy a smart contract locally using Forge

To find out more about forge’s capabilities type

forge --help

Each blockchain (private or public) has an RPC URL (RPC SERVER) that acts as an endpoint. When we tried to deploy our smart contract, forge tried to use http://localhost:8545/, which doesn't host any blockchain. Thus, let's try to deploy our smart contract specifying the place where we want to deploy it.

forge create SimpleStorage --rpc-url <http://127.0.0.1:8545> --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efe784d7bf4f2ff80

*private key is invalid

Private Key Safety

Having a private key in plain text is extremely bad. The private key(s) we used in the last lesson are well-known keys for local testing, you shouldn’t use those on mainnet and keeping them in plain text is ok, but any other private key should be kept hidden, especially your production key or key’s associated with accounts that hold crypto.

Moreover, it’s very bad to have private keys in bash history (hit the up arrow and see the key you used to deploy).

You can delete your history by typing:

history -c

Deploy a smart contract locally using Anvil

In Foundry we keep our scripts in the script folder.

Please create a new file called DeploySimpleStorage.s.sol.

Using .s.sol as a suffix is a naming convention for Foundry scripts, in future lessons, when we'll write Foundry tests, these will bear the suffix of .t.sol.

// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import {Script} from "forge-std/Script.sol";
import {SimpleStorage} from "../src/SimpleStorage.sol";
contract DeploySimpleStorage is Script {
function run() external returns (SimpleStorage) {
vm.startBroadcast();
SimpleStorage simpleStorage = new SimpleStorage();
vm.stopBroadcast();
return simpleStorage;
}
}

run is an external function that will return the SimpleStorage contract.

In the Run function, we are going to use a distinctive keyword: vm. Foundry has a distinctive feature known as cheat codes. The vm keyword is a cheat code in Foundry, and thereby only works in Foundry.

vm.startBroadcast indicates the starting point for the list of transactions that get to be sent to the RPC URL;

Similarly, vm.stopBroadcast indicates the ending point of the list of transactions that get to be sent to the RPC URL;

forge script script/DeploySimpleStorage.s.sol --rpc-url <http://127.0.0.1:8545>
[⠆] Compiling...
[⠔] Compiling 2 files with 0.8.19
[⠒] Solc 0.8.19 finished in 1.08s
Compiler run successful!
Script ran successfully.
Gas used: 338569
== Return ==
0: contract SimpleStorage 0x90193C961A926261B756D1E5bb255e67ff9498A1
If you wish to simulate on-chain transactions pass a RPC URL.

Hit the up arrow key and add --broadcast --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7f4f2ff80 at the end.

forge script script/DeploySimpleStorage.s.sol --rpc-url <http://127.0.0.1:8545> --broadcast --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
Transaction: 0x73eb9fb4ef7b159e03c50d669c42e2ec4eeaa9358bea0a710cb07168e5192570
Contract created: 0x5fbdb2315678afecb367f032d93f642f64180aa3
Gas used: 357088
    Block Number: 1
Block Hash: 0x8ea564f146e04bb36fc27f0b491223a023b5882d2fcfce3ff85e0dd152e611e4
Block Time: "Tue, 16 Apr 2024 13:39:51 +0000"

Having our private key in plain text is very bad,

Create a new file in the root of your project called .env. Then, go the .gitignore file and make sure .env is in there.

The .env file will host environment variables. Variables that are of a sensitive nature that we don't want to expose in public.

PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
RPC_URL=http://127.0.0.1:8545
forge script script/DeploySimpleStorage.s.sol --rpc-url $RPC_URL --broadcast --private-key $PRIVATE_KEY

we showed you how to configure and use a .env file to hold your private key and rpc url, some developments have taken place since that lesson was made so ... You should never use a .env again.

Encrypting your Keys Using ERC2335

For now, let’s pretend our private key is this:

0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 (key 0 from Anvil)

Type the following command in your terminal

cast wallet import nameOfAccountGoesHere --interactive

Foundry has a built-in tool known as Cast. Cast comes loaded with numerous commands to interact with. Learn more about them by typing cast --help. One such useful command is send which is designed to sign and publish a transaction. To view help about send, type cast send --help.

To use send we need a signature and some arguments.

cast send 0x5FbDB2315678afecb367f032d93F642f64180aa3 "store(uint256)" 1337 --rpc-url $RPC_URL --private-key $PRIVATE_KEY

What did we just do?

Let’s break it down:

  • cast send is the command we used to sign and publish our transaction;
  • 0x5FbDB2315678afecb367f032d93F642f64180aa3 or any other address is the target of our cast send, the contract we are interacting with;
  • "store(uint256)" is the signature of the function we are calling.
  • 1337 is the number we pass to the store function. As we can see in the function signature, we are expected to provide an uint256 input. You can obviously provide any number you want, as long as it fits uint256.
  • you already know what -rpc-url $RPC_URL --private-key $PRIVATE_KEY are. The place where we send and the private key we use to sign.

Reading information from the blockchain

cast conveniently provides a way to read information stored on the blockchain. Type cast call --help in your terminal to find out more. It works similarly to send, where you have to provide a signature and some arguments. The difference is you are only peering into the storage, not modifying it.

Call the following command in your terminal:

cast call 0x5FbDB2315678afecb367f032d93F642f64180aa3 "retrieve()"

We receive back the following:

0x0000000000000000000000000000000000000000000000000000000000000539

This represents a hex value. In the previous lessons, we learned how to convert this to a normal number.

Type the following command in your terminal:

cast --to-base 0x0000000000000000000000000000000000000000000000000000000000000539 dec

Thank you for reading, I hope this article helped you understand the concepts.

Connect with me:

Linkedin | Email | Medium | X

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

No responses yet

Write a response