By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
A Web3 developer portfolio is a curated collection of open‑source code, live dApp demos, and competition results that proves you can design, build, and ship decentralized applications. Because every smart‑contract deployment is immutable and publicly verifiable, a strong portfolio lets recruiters and investors instantly audit your technical chops and product sense. Think of a portfolio like a “GitHub résumé” for crypto: a Uniswap‑style token swap you coded from scratch, an NFT‑minting site that writes to IPFS, and a DAO voting contract you showcased at a hackathon.
Solidity ≥ 0.8.20: The primary language for EVM contracts. solidity pragma solidity ^0.8.20; contract SimpleERC20 { /* … */ }
solidity pragma solidity ^0.8.20; contract SimpleERC20 { /* … */ }
Hardhat: A local development environment that compiles, tests, and deploys contracts. bash npx hardhat compile npx hardhat run scripts/deploy.js --network goerli
bash npx hardhat compile npx hardhat run scripts/deploy.js --network goerli
Ethers.js Provider/Signer: JavaScript objects that read chain state (provider) and send transactions (signer). js const provider = new ethers.JsonRpcProvider(INFURA_GOERLI); const signer = provider.getSigner();
provider
signer
js const provider = new ethers.JsonRpcProvider(INFURA_GOERLI); const signer = provider.getSigner();
ERC‑20 transferFrom pattern: Allows a spender to move tokens on behalf of an owner after approve. solidity token.transferFrom(owner, recipient, amount);
transferFrom
approve
solidity token.transferFrom(owner, recipient, amount);
ERC‑721 Mint Function: Creates a new NFT and assigns it to a wallet. solidity function mint(address to, uint256 tokenId) external { _safeMint(to, tokenId); }
solidity function mint(address to, uint256 tokenId) external { _safeMint(to, tokenId); }
IPFS CID (Content Identifier): A hash that points to immutable off‑chain data (e.g., NFT metadata). js const cid = await ipfs.add(JSON.stringify(metadata));
js const cid = await ipfs.add(JSON.stringify(metadata));
GitHub Actions CI/CD: Automates linting, testing, and deployment on every push. ```yaml
name: Run tests run: npx hardhat test ```
Chainlink VRF (Verifiable Random Function): On‑chain source of randomness for fair draws. solidity requestRandomWords(keyHash, subscriptionId, 3, 200000, 1);
solidity requestRandomWords(keyHash, subscriptionId, 3, 200000, 1);
Optimistic Rollup (e.g., Arbitrum): Scales Ethereum by assuming transactions are valid and only posting fraud proofs when challenged.
ZK‑Rollup (e.g., zkSync): Packs many transactions into a single proof that is verified on‑chain, offering privacy and lower gas.
DAO Governance vote(uint256 proposalId, bool support): Simple on‑chain voting function.
vote(uint256 proposalId, bool support)
Reentrancy Guard (nonReentrant modifier): Prevents a contract from being called back into before the first call finishes. solidity modifier nonReentrant() { require(!locked, "Reentrancy"); locked = true; _; locked = false; }
nonReentrant
solidity modifier nonReentrant() { require(!locked, "Reentrancy"); locked = true; _; locked = false; }
npx hardhat init
contracts/
test/
chai
ethers
npx hardhat test
npx hardhat run scripts/deploy.js --network goerli
wagmi
Mistake: Hard‑coding tx.origin for access control. Correction: Use msg.sender and role‑based AccessControl because tx.origin can be spoofed through phishing contracts.
tx.origin
msg.sender
AccessControl
Mistake: Forgetting to await asynchronous ethers calls, leading to “nonce too low” errors. Correction: Always await contract.method(...).wait() so the transaction is mined before the next step.
await
contract.method(...).wait()
Mistake: Deploying contracts with the default Solidity optimizer disabled, causing high gas fees. Correction: Enable optimizer: { enabled: true, runs: 200 } in hardhat.config.js to shrink bytecode and lower gas.
optimizer: { enabled: true, runs: 200 }
hardhat.config.js
Mistake: Storing large NFT metadata on‑chain (e.g., base64 strings). Correction: Store only the IPFS CID on‑chain; keep the JSON and image off‑chain to keep gas cheap.
Mistake: Using a single private key for both testnet and mainnet deployments. Correction: Separate keys (or use a hardware wallet) to avoid accidental mainnet loss and to keep testnet credentials public‑friendly.
call
delegatecall
tokensReceived
estimateGas
Scenario: A contract uses tx.origin to restrict withdrawals to the contract owner. Answer: Dangerous – a malicious contract can trick the owner into calling it, making tx.origin the attacker’s address, thus bypassing the check.
Scenario: Your front‑end calls contract.transfer(address, amount) but the transaction reverts with “insufficient allowance”. Answer: You must first approve the spender (your contract) for that amount; transferFrom requires an allowance set by the token holder.
contract.transfer(address, amount)
Scenario: You see a DAO proposal that can be executed by anyone after the voting period ends. Answer: Ensure the execution function checks proposal.state == Passed && block.timestamp >= endTime to prevent premature or unauthorized execution.
proposal.state == Passed && block.timestamp >= endTime
uint256
uint128
^0.8.0
bafy...
Qm...
npx hardhat node --fork https://eth-mainnet.alchemyapi.io/v2/KEY
actions/setup-node@v4
actions/cache@v3
node_modules
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.