# Week 14 at Blockfuse Labs: My Journey with Foundry, Building a School Management System and an NFT Marketplace When I first heard about **Foundry**, I thought, *“Here w**Blockfuse Labs** changed that. Instead of feeling overwhelmed, I discovered how powerful Foundry is — not just for writing smart contracts, but for testing, debugging, and deploying them faster than I imagined. This week, I built two projects that pushed me out of my comfort zone: 1. A **School Management System** smart contract. 2. An **NFT Marketplace** where people could mint, buy, and sell NFTs. It was one of the most exciting weeks so far. ## Discovering Foundry Foundry is like having a turbo engine for smart contract development. It comes with two main tools: * **Forge** → for building, testing, and deploying contracts. * **Cast** → for sending transactions and reading data from contracts. Here are the basic commands I learned: ### Foundry Setup Commands ```bash forge init myProject # Create a new project forge build # Compile contracts forge test # Run all tests forge test -vvv # Run tests with detailed logs forge clean # Clear build cache forge install OpenZeppelin/openzeppelin-contracts # Install dependencies forge update # Update dependencies ``` ### Cast Commands ```bash cast call <address> "<functionSignature>" <args> # Call a contract function cast send <address> "<functionSignature>" <args> # Send a transaction cast block-number # Get current block number cast balance <address> # Get ETH balance ``` ## Project 1: School Management System I revisited the **School Management System** idea from earlier weeks but rebuilt it in Foundry. ### Features I implemented: * **Admin** can register students. * **Admin** can assign grades. * Students’ data (name + grade) is stored on-chain. ### Smart Contract Example ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.17; contract School { address public admin; struct Student { string name; uint grade; } mapping(address => Student) public students; constructor() { admin = msg.sender; } function registerStudent(address student, string memory name) external { require(msg.sender == admin, "Only admin can register"); students[student] = Student(name, 0); } function assignGrade(address student, uint grade) external { require(msg.sender == admin, "Only admin can assign grades"); students[student].grade = grade; } } ``` ## Writing Tests in Foundry The beauty of Foundry is that you write tests directly in Solidity. ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.17; import "forge-std/Test.sol"; import "../src/School.sol"; contract SchoolTest is Test { School school; address admin = address(this); address student = address(0xBEEF); function setUp() public { school = new School(); } function testRegisterStudent() public { school.registerStudent(student, "Alice"); (string memory name, uint grade) = school.students(student); assertEq(name, "Alice"); assertEq(grade, 0); } function testOnlyAdminCanRegister() public { vm.prank(address(0xCAFE)); // impersonate another account vm.expectRevert(); school.registerStudent(student, "Bob"); } } ``` ### Useful Foundry Cheatcodes (via `vm`) * `vm.prank(addr)` → impersonates another account. * `vm.expectRevert()` → expect a function to fail. * `vm.warp(timestamp)` → fast-forward time. * `vm.deal(addr, amount)` → give ETH to an account. * `vm.roll(blockNumber)` → set block number. * `vm.snapshot()` / `vm.revert(snapshotId)` → save and restore blockchain state. --- ## Project 2: NFT Marketplace After the school system, I built an **NFT Marketplace**. ### Features: * Users can mint NFTs. * Owners can list NFTs for sale. * Buyers can purchase NFTs. ### Contract Example ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.17; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; contract NFTMarket is ERC721 { uint public nextTokenId; address public admin; struct Listing { uint tokenId; uint price; address seller; } mapping(uint => Listing) public listings; constructor() ERC721("MyNFT", "MNFT") { admin = msg.sender; } function mint(address to) external { _safeMint(to, nextTokenId); nextTokenId++; } function list(uint tokenId, uint price) external { require(ownerOf(tokenId) == msg.sender, "Not owner"); listings[tokenId] = Listing(tokenId, price, msg.sender); } function buy(uint tokenId) external payable { Listing memory listing = listings[tokenId]; require(msg.value == listing.price, "Incorrect price"); _transfer(listing.seller, msg.sender, tokenId); payable(listing.seller).transfer(msg.value); delete listings[tokenId]; } } ``` ## Testing the Marketplace in Foundry ```solidity pragma solidity ^0.8.17; import "forge-std/Test.sol"; import "../src/NFTMarket.sol"; contract NFTMarketTest is Test { NFTMarket market; address alice = address(0xABCD); address bob = address(0x1234); function setUp() public { market = new NFTMarket(); } function testMintAndListNFT() public { vm.prank(alice); market.mint(alice); vm.prank(alice); market.list(0, 1 ether); (uint tokenId, uint price, address seller) = market.listings(0); assertEq(tokenId, 0); assertEq(price, 1 ether); assertEq(seller, alice); } function testBuyNFT() public { vm.deal(alice, 1 ether); vm.deal(bob, 2 ether); vm.prank(alice); market.mint(alice); vm.prank(alice); market.list(0, 1 ether); vm.prank(bob); market.buy{value: 1 ether}(0); assertEq(market.ownerOf(0), bob); } } ``` --- ## Foundry Commands I Used for This Project Here’s the cheat sheet of commands that carried me through Week 14: ### Compilation & Testing ```bash forge build # Compile contracts forge test # Run tests forge test -vvv # Run tests with detailed logs forge test --match-test testBuyNFT # Run a single test ``` ### Gas Reporting ```bash forge test --gas-report # Run tests and show gas usage ``` ### Coverage ```bash forge coverage # Check test coverage ``` ### Deployments ```bash forge script script/Deploy.s.sol --rpc-url <RPC_URL> --private-key <KEY> --broadcast ``` ### Cast Utilities ```bash cast balance <address> # Get ETH balance cast call <address> "ownerOf(uint256)" 0 # Read NFT owner cast send <address> "mint(address)" <to> --private-key <KEY> --rpc-url <RPC_URL> ``` --- ## Summary Of Week 14 By the end of the week, I realized: 1. **Foundry is lightning-fast** — no waiting for TypeScript, just Solidity tests running instantly. 2. **Cheatcodes give control** — I could impersonate accounts, fast-forward time, or fund wallets. 3. **Testing = confidence** — I could simulate real-world scenarios (students registering, NFTs being bought) safely. 4. **Commands matter** — Foundry’s simplicity comes from its CLI. Once you memorize `forge build`, `forge test`, and `cast call`, you feel unstoppable. --- ## Looking Ahead Week 14 made me feel like I unlocked a new level of blockchain development. With Foundry, I don’t just write contracts — I **test them deeply**, **analyze gas usage**, and **interact with them live** using Cast. Next, I want to try: * **Property-based testing** (`forge fuzz`) to check random inputs. * **Mainnet forking** (`--fork-url`) to simulate real Ethereum conditions. For now, I’m just happy that I built a **school on-chain** and a **marketplace for NFTs** — and proved they worked, line by line, with Foundry.