The following article is based on Adam’s CharmingData channel and GitHub repository. ♥️
♥️ Info: Are you AI curious but you still have to create real impactful projects? Join our official AI builder club on Skool (only $5): SHIP! - One Project Per Month
In this tutorial, we will create, test, and deploy a smart contract called SimpleStorage. This contract will allow your users to create their own sentence and store it on the blockchain. It will also allow users to retrieve the last sentence stored and display it on the page.

Consider the following Solidity contract:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
contract SimpleStorage {
// Define a string called storeTheSentence. This is a state variable, which will be permanently stored in the blockchain.
string storeTheSentence;
constructor(string memory initialSentence) {
// Assign the value of initialSentence to the storeTheSentence variable
storeTheSentence = initialSentence;
}
// Declares a function called getSentence
// Solidity funcions visibility: public, private, internal and external
// Solidity view functions: https://www.geeksforgeeks.org/solidity-view-and-pure-functions/
function getSentence() public view returns (string memory) {
return storeTheSentence;
}
// Declare a function called setSentence
// The function takes 1 input parameter, a string named newSentence, with the calldata data location in the Ethereum Virtual Machine
function setSentence(string calldata newSentence) external {
// Assign the value of newSentence to the storeTheSentence variable
storeTheSentence = newSentence;
}
}This is a simple smart contract written in Solidity, the most popular programming language for implementing smart contracts on the Ethereum blockchain. The contract’s name is SimpleStorage, and it primarily focuses on storing and retrieving a string (a sequence of characters).
Here’s a brief breakdown of the contract:
- State variable (
storeTheSentence): This is a string variable that will store a sentence. This variable’s value is stored on the blockchain, making it a permanent, unerasable record. - Constructor function: When the contract is first deployed to the Ethereum blockchain, the constructor function is executed once. This function accepts one argument, a string (
initialSentence), and assigns its value to the state variablestoreTheSentence. getSentence()function: This function is apublic viewfunction, which means anyone can call it to read the value ofstoreTheSentencewithout changing any data or state in the contract. It does not cost any gas to call this function because it doesn’t change the state of the blockchain.setSentence()function: This function is declared asexternal, meaning it can only be called from outside the contract. It accepts one string argument (newSentence) and assigns its value tostoreTheSentence, effectively updating the stored sentence. As this function modifies the state of the contract, it requires a transaction to be sent and will cost gas to execute.
In essence, this contract allows anyone to store a sentence on the Ethereum blockchain and retrieve it. Due to the permanent and public nature of blockchain storage, the stored sentence would be visible to anyone and cannot be erased or modified once set (except by calling the setSentence function again).
Let’s learn how to set it up in a step-by-step manner next. 👇
Backend
- Open the terminal (command line), create two new folders called
simple-storageandbackend. Go into thebackendfolder.
mkdir simple-storage cd simple-storage mkdir backend cd backend
- Set up a Hardhat project. Install the necessary libraries, by typing in the terminal:
npm init --yes npm install --save-dev --save-exact hardhat@2.14.0 npm install dotenv
- This library might be necessary to install as well, especially if you’re a Windows user:
npm install --save-dev @nomicfoundation/hardhat-toolbox@2
- Make sure you are still in the
backenddirectory. Now, create a sample contract project by typing in the terminal:
npx hardhat
- Select
Create a Javascript Project. Don’t change anything in the Hardhat project root, just click enter. Yes, add a.gitignore.
- Open the
backendfolder and remove any present contracts inside thecontractsfolder. Insert yourSimpleStoragecontract. - Now, inside the
scriptsfolder, replace the contect of thedeploy.jsfile with the deploy.js code from this project. - Create a
.envfile inside thebackendfolder. This will be used to store your wallet key and your Quicknode endpoint. A QuickNode API endpoint gives you quick access to a network of nodes.
- Add these two lines inside the
.envfile, and update the content inside the quotation marks:
QUICKNODE_HTTP_URL="your-quicknode-http-provider-goes-here-inside-the-quotation-marks" PRIVATE_KEY="your-wallet-private-key-goes-here-inside-the-quotation-marks"
- Open the
hardhat.config.jsfile inside thebackendfolder and replace its content with the hardhat.config.js code from this project. - Compile your Contract by going back to your terminal (ensure you are in the
backenddirectory). And type:
npx hardhat compile
- Every time you modify your contract (
SimpleStorage), you will have to repeat the above compile step.
- With your contract compiled, now we can deploy it to the sepolia testnet. In your terminal type:
npx hardhat run scripts/deploy.js --network sepolia
Save the contract address that was printed out. Go to https://sepolia.etherscan.io/ and insert the contract address into the Explorer input field. Take some time to explore the transaction details of your contract.
- Save this address somewhere. Don’t lose it!
Testing
Every Contract should be tested before deployment. In this case we deployed first becuause it’s freaking exciting to see our contract deployed. But we need tests to make sure our contract has no bugs and is secure.
- Open the
testfolder and remove any present files inside of it. Create a new file calledtesting.js, and insert the testing.js code from this project. - Go back to the terminal, make sure you’re in the
backenddirectory, and type:
npx hardhat test
Frontend
In this section of the tutorial we’ll create a dApp (decentralized app) that will connect to your contract and its functions, allowing you to interact with it. In other words, we’re building an interface for the contract.
- Open the terminal (command line) and go into the
simple-storagedirectory. Create a sample Next app by typing:
npx create-next-app@13 frontend
- Make sure to choose these settings.

- Before running the sample app, you’ll need to remove the
.gitfile that was automatically created inside the newfrontendfolder. To remove the file, type this command inside the terminal:
# Linux / macOS cd frontend rm -rf .git # Windows cd frontend rm -r -fo .git
- Install these packages using your terminal (you should still be in the
frontenddirectory).
npm install web3modal npm install ethers@5
- Create a new folder called
constantswithin thefrontenddirectory. Inside theconstantsfolder create a new file calledindex.js. Add the following code insideindex.js.
export const MY_CONTRACT_ADDRESS = "MY_CONTRACT_ADDRESS"; export const abi = MY_ABI;
- Replace the
MY_ABIwith the abi array that can be found in the following file:backend/artifacts/contracts/SimpleStorage.json - Replace the
MY_CONTRACT_ADDRESSwith the address of the contract that you deployed in the Backend section of this tutorial.
- Finally, to build the interface of the contract, open the
index.jsfile under thepagesfolder (in thefrontendfolder) and replace its content with the index.js code from this project. - Add the Charming Data images using the instructions below. Once you understand how to add images to your app, feel free to replace with your own images, in which case you would need to update the images’ names inside the
pages/index.jsfile (lines 143 & 154)
- Add the logo-charmingdata-small.ico and logocharmingdata.png to the public folder inside the frontend directory. Do not change image names.
- Go back to your terminal; make sure your in the
frontenddirectory and type:
npm run dev
Sharing your dApp with others
We will use Vercel to deploy the frontend of our contract. Before starting with Vercel you will need to create a GitHub account if you don’t have one and push your code into a GitHub repository:
- Once your repositoy has been created in Github, go to Vercel and create an account by connecting your GitHub account.
- Once your GitHub account is connected, click the button to add a new project in Vercel.
- add your repository (you might have to import it as well)
- Select
Next.jsas the Framework Preset. In the Root Directory click Edit to selectfrontend. - Click Deploy, and wait a few minutes. When done, click your domain link to see your dApp.
The previous text was originally written by Adam from CharmingData.
