Goal. You will: (1) set up Truffle, (2) write
Greeter.sol
, (3) compile, (4) deploy (migrate) to a local blockchain, and (5) read the greeting via a script.
Works on Windows, macOS, Linux. If lab PCs block global installs, use the “no-global” commands below.
0) What is a “Terminal” and where do I open it?
Terminal = a text window where you type commands (like node -v
, truffle init
). Also called command line, shell, or console.
On Windows
- Command Prompt (CMD): Win → type cmd → Enter.
- PowerShell: Win → type PowerShell → Enter.
- Windows Terminal: Win → type Windows Terminal → Enter.
- Open terminal in a folder:
- In File Explorer, go to the folder, click the address bar, type
cmd
→ Enter. - Or Shift+Right-click inside the folder → “Open in Terminal”.
- In File Explorer, go to the folder, click the address bar, type
On macOS
- Terminal: Cmd+Space → type Terminal → Enter.
- From Finder in a folder: Right-click → New Terminal at Folder (enable in Settings → Keyboard → Keyboard Shortcuts → Services).
On Linux
- Press Ctrl+Alt+T, or search “Terminal”.
Inside VS Code (any OS)
- Open your project in VS Code → menu View ▸ Terminal (or Ctrl+`).
- The terminal starts in the folder shown in VS Code’s Explorer.
Basic navigation you’ll use:
# show where you are
pwd # macOS/Linux
cd # Windows PowerShell (prints current path)
# list files
ls # macOS/Linux
dir # Windows
# go into your project
cd my_truffle_project
# go up one folder
cd ..
IMPORTANT: Before running commands like
truffle init
or truffle compile
,
make sure your terminal’s current folder is your project folder (e.g., .../my_truffle_project
).
If not, use cd
to go there first.
🆕 First time? Folder preview after
truffle init
:
my_truffle_project/
contracts/
Migrations.sol
migrations/
1_initial_migration.js
test/
truffle-config.js
You will add: contracts/Greeter.sol, migrations/2_deploy_greeter.js, and create scripts/scripts_test.js.
1) Setup
- Install Node.js (LTS or v22). Verify:
node -v npm -v
- Install Truffle:
npm install -g truffle
No global installs? Use:npm i -D truffle npx truffle version
- Create project:
mkdir my_truffle_project cd my_truffle_project truffle init
FYI You do not need to edit
truffle-config.js
for local development; Truffle Develop provides sane defaults.2) Contract & Migration (exact save locations)
contracts/Greeter.sol
📂 Where to save:
Windows example:
my_truffle_project/contracts/Greeter.sol
Windows example:
C:\Users\YourName\my_truffle_project\contracts\Greeter.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Greeter {
string public greeting;
constructor(string memory _greeting) {
greeting = _greeting;
}
function greet() public view returns (string memory) {
return greeting;
}
}
migrations/2_deploy_greeter.js
📂 Where to save:
Windows example:
my_truffle_project/migrations/2_deploy_greeter.js
Windows example:
C:\Users\YourName\my_truffle_project\migrations\2_deploy_greeter.js
const Greeter = artifacts.require("Greeter");
module.exports = function (deployer) {
deployer.deploy(Greeter, "Hello, JU!"); // change greeting if you like
};
Make the scripts folder & interaction script
📂 Where to save: create the folder
Windows example:
my_truffle_project/scripts
(if it doesn't exist), then save scripts_test.js
inside it.Windows example:
C:\Users\YourName\my_truffle_project\scripts\scripts_test.js
const Greeter = artifacts.require("Greeter");
module.exports = async function (callback) {
try {
const instance = await Greeter.deployed();
console.log("Contract address:", instance.address);
const greeting = await instance.greet();
console.log("Greeting:", greeting);
} catch (err) {
console.error(err);
}
callback();
};
Compile (build ABIs/artifacts)
truffle compile
Compile vs. Migrate — when to run which?
• Compile: turn Solidity into JSON artifacts in
• Migrate: deploy contracts using files in
• Changed only the migration (e.g., constructor args)?
• Changed the contract code? Run
• Compile: turn Solidity into JSON artifacts in
build/contracts/
. Run after you change Solidity.• Migrate: deploy contracts using files in
migrations/
. Run to put contracts on the chain.• Changed only the migration (e.g., constructor args)?
migrate --reset
is enough.• Changed the contract code? Run
compile
then migrate --reset
.
3) Start Local Blockchain & Deploy
Start Truffle Develop (spins up a local chain + console):
truffle develop
Inside the special prompt truffle(develop)>
, type commands without the truffle
prefix:
compile
migrate
test # optional
Two-terminal option Keep truffle develop
open; in another terminal you can run truffle migrate --network development
. For beginners, staying inside the console is simpler.
4) Interact via Script
Run inside the Truffle console
At the truffle(develop)>
prompt:
exec scripts/scripts_test.js
Run from a normal terminal (keep develop
running)
truffle exec scripts/scripts_test.js --network development
5) Expected Output
Contract address: 0x...YOUR_DEPLOYED_ADDRESS
Greeting: Hello, JU!
6) Copy/Paste Tips (Windows & Truffle console)
- CMD: Right-click to paste (or enable “QuickEdit Mode”: title bar → Properties → QuickEdit).
- PowerShell: Ctrl+V pastes; Ctrl+C may interrupt; use right-click or Ctrl+Shift+V.
- Truffle console is still your terminal; paste works the same. If flaky, try Windows Terminal or run from a second terminal with
truffle <cmd>
.
7) Troubleshooting
- Node/npm missing: Install Node. Check with
node -v
,npm -v
. - “Could not connect to your Ethereum client”: Start
truffle develop
first, or use--network development
. - Global installs blocked (lab PCs):
npm i -D truffle npx truffle init npx truffle develop
- Port conflict / firewall:
(Optional: add a matchingtruffle develop --port 8545
development
entry intruffle-config.js
.) - Reset bad deployment:
migrate --reset
- Changed Solidity? Rebuild then redeploy:
compile migrate --reset
8) What next? Turn this into a tiny dapp (frontend)
Now that you can deploy and read the greeting in Node, let’s make a one-page web dapp that reads from the deployed contract.
- Find your ABI JSON & address (after compiling & migrating):
- ABI file:
my_truffle_project/build/contracts/Greeter.json
(this is a big JSON with ABI + networks). - Deployed address: shown after
migrate
and also inside that JSON undernetworks
→ (network id like5777
) →address
.
- ABI file:
- Create a simple frontend (put this
index.html
next to your project or in a new folder):
📂 Where to save (simplest): Create a new folder like
my_dapp
, save the file below as index.html
inside it.<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Greeter Dapp</title>
</head>
<body style="font-family:system-ui;padding:20px">
<h1>Greeter Dapp</h1>
<button id="connect">Connect MetaMask</button>
<div id="out" style="margin-top:12px"></div>
<script src="https://cdn.jsdelivr.net/npm/ethers@6.13.2/dist/ethers.umd.min.js"></script>
<script>
// 1) Paste ABI from build/contracts/Greeter.json (only the "abi" array)
const ABI = [
{"inputs":[{"internalType":"string","name":"_greeting","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},
{"inputs":[],"name":"greet","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},
{"inputs":[],"name":"greeting","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}
];
// 2) Set ADDRESS to your deployed contract address printed by migrate
const ADDRESS = "PASTE_YOUR_DEPLOYED_ADDRESS_HERE";
const out = (msg) => document.getElementById('out').innerText = msg;
document.getElementById('connect').onclick = async () => {
if (!window.ethereum) { out('Install MetaMask first.'); return; }
// Request accounts and connect to the browser provider (MetaMask)
await window.ethereum.request({ method: 'eth_requestAccounts' });
const provider = new ethers.BrowserProvider(window.ethereum);
// 3) Ensure MetaMask is on the same network as your contract (Truffle Develop is usually 5777)
const net = await provider.getNetwork();
console.log('Connected network:', net);
// 4) Read greeting
const contract = new ethers.Contract(ADDRESS, ABI, provider);
const g = await contract.greet();
out('Greeting: ' + g);
};
</script>
</body>
</html>
Very important: If you re-deploy the contract, the address changes. Update
ADDRESS
in your frontend. If you change the Solidity interface, re-copy the ABI from Greeter.json
.Prefer React/Vite later?
# from a parent folder
npm create vite@latest my-react-dapp -- --template react
cd my-react-dapp
npm i
npm i ethers
npm run dev
Then put ABI + address in a config and call via
ethers.BrowserProvider
similarly.9) Later: replacing files for new assignments
- Replace Solidity: put your new contract in
contracts/
. Then:compile migrate --reset
- Replace migration: update
migrations/2_deploy_*.js
(constructor args, contract name). Then:migrate --reset
- Replace the script: edit
scripts/scripts_test.js
for new function names. Then:exec scripts/scripts_test.js # inside develop console # or truffle exec scripts/scripts_test.js --network development
- Frontend JSON (“the ABI file”): after compile, re-copy ABI from
build/contracts/<YourContract>.json
and update the deployed address in your frontend.
Remember: Changing contract code ⇒ new ABI and usually a new address. Your UI must be updated with both.
Submission: Zip your project (omit
node_modules
) or push to a repo. Include screenshot(s) showing the contract address and greeting.