Web3 step by step #2: Smart contract
After #1, you have a local block chain and sample project with hardhat. So, let’s get on developing our smart contract for our tipping dApp.

Introduction
If you missed the first article, then head on over to part 1 in the series. We will follow these steps:
- Create a new smart contract called TipMe.sol
- Add a test script for our smart contract and run a test
- Deploy the smart contract to our local blockchain we setup in step #1.
1. Create a new smart contract
Open VSCode to the main project folder, which should be called ‘hardhattest’. Now create a new file in the contracts folder as below and call it TipMe.sol

//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;import "hardhat/console.sol";contract TipMe {address payable public owner; // set to payable so we can tip the contractuint256 public totalTips;struct Tips {
address tiper;
string message;
uint256 timestamp;
uint256 amount;
}Tips[] public tips;/*
* Construct emits console message and sets owner of the contract to account deploying
*/
constructor() {
console.log("Deploying TipMe contract:");
owner = payable(msg.sender);
}/*
* Approve the tip
*/
function approve(string memory _message) public payable virtual {
console.log(msg.value);
totalTips += msg.value;
tips.push(Tips(msg.sender, _message, block.timestamp, msg.value));
}/*
* On destorying the contract send funds to the owner so they not locked
*/
function destroy() public {
if (msg.sender == owner) {
selfdestruct(owner);
}
}
}
You can see that we have 2 public properties so we can get to the tip total and tips array. Our important method is the approve which receives the tip and stores details in the array.
Important, approve is payable so will receive a tip amount in msg.value
2. Add a test script for our smart contract and run a test
Now, we need to add a local test file so we can run some local test scripts to be sure all is working before we deploy. We test the following scenarios:
- Deploy the contract
- Approve a tip and check the NONCE we receive is zero
- Get the contract balance and confirm its 0.5 eth
- Check the tips public array first row for a correct address
const { expect } = require("chai");
const { ethers } = require("hardhat");
describe("Tipme", function () {it("Should return the first NONCE once its done", async function () {
/*
* Setup and deploy tipme contract
*/
const TipMe = await ethers.getContractFactory("TipMe");
const tipme = await TipMe.deploy();
await tipme.deployed(); /*
* Get signed accounds
*/
const [owner, addr1] = await ethers.getSigners(); /*
* Let's try to tip the contract from Addr1
*/
console.log("Tipping");
let result = await tipme
.connect(addr1)
.approve("Thanks so much for your help", {value: ethers.utils.parseEther("0.5")}); /*
* expect NONCE to be 0
*/
expect(result?.nonce).to.equal(0); /*
* Get Contract balance & expect to be 0.5
*/
let contractBalance = await hre.ethers.provider.getBalance(tipme.address);
console.log("Contract balance:",hre.ethers.utils.formatEther(contractBalance)); expect(contractBalance).to.equal(ethers.utils.parseEther("0.5"));
result = await tipme.connect(addr1).tips(0); expect(result?.tiper).to.equal(addr1.address); });
});
Now that your test is setup, make your way in your CLI to your project’s main folder and execute the following command:
npm hardhat test
If you installed hardhat using yarn, then feel free to use it, while if you have not installed hardhat, you can use npx.
You should get a result as below:
@Shauns-MBP-475 ~/D/c/A/hardhattest> yarn hardhat test 1
yarn run v1.22.0
warning package.json: No license field
warning ../../../../package.json: No license field
$ /Users/shaun/Documents/code/AVAX/hardhattest/node_modules/.bin/hardhat testTipme
Deploying TipMe contract:
Tipping
500000000000000000
Contract balance: 0.5
✔ Should return the first NONCE once its done (896ms)1 passing (899ms)✨ Done in 1.93s.
Well done, we are almost done, you now just need to deploy to your local hardhat blockchain.
3.
From your projects main folder, you can now startup hardhat as follows. I like verbose as you get lots of details 😉
yarn hardhat node --verbose
You will see your blockchain is running and it will give you your valid account numbers with their ETH balances:
Accounts
========WARNING: These accounts, and their private keys, are publicly known.
Any funds sent to them on Mainnet or any other live network WILL BE LOST.Account #0: 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266 (10000 ETH)
Private Key: 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80Account #1: 0x70997970c51812dc3a010c7d01b50e0d17dc79c8 (10000 ETH)
Private Key: 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d
Now, create a new terminal and again in the main folder, lets deploy our smartcontract.
Tip: Whenever you restart hardhat, you need to redeploy your contracts.
yarn hardhat run scripts/sample-script.js
You will now see the result
yarn run v1.22.0
warning package.json: No license field
warning ../../../../package.json: No license field
$ /Users/shaunenslin/Documents/code/AVAX/hardhattest/node_modules/.bin/hardhat run scripts/sample-script.js
Compiled 1 Solidity file successfully
Deploying TipMe contract:
TipMe deployed to: 0x5FbDB2315678afecb367f032d93F642f64180aa3
✨ Done in 5.34s.
Conclusion
Congrat yourself on having deployed your first contract….
Come back next week and we will develop our dApp.