By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
ERC (Ethereum Request for Comments) standards are a set of interface contracts that define how tokens behave on the Ethereum Virtual Machine. By agreeing on a common API, anyone can write wallets, exchanges, or marketplaces that work with any token that follows the standard—just like USB‑C works for every peripheral. Real‑world example: A user clicks “Swap” on Uniswap, and the front‑end calls the ERC‑20 transferFrom function of the token they are selling; the same UI would work for DAI, USDC, or a brand‑new meme coin without any code changes.
transferFrom
ERC‑20 – The baseline fungible‑token interface (totalSupply, balanceOf, transfer, approve, transferFrom). solidity interface IERC20 { function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function transfer(address to, uint256 amount) external returns (bool); function approve(address spender, uint256 amount) external returns (bool); function transferFrom(address from, address to, uint256 amount) external returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); }
totalSupply
balanceOf
transfer
approve
solidity interface IERC20 { function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function transfer(address to, uint256 amount) external returns (bool); function approve(address spender, uint256 amount) external returns (bool); function transferFrom(address from, address to, uint256 amount) external returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); }
ERC‑721 – The non‑fungible token (NFT) standard; each token has a unique tokenId. solidity interface IERC721 { function ownerOf(uint256 tokenId) external view returns (address); function safeTransferFrom(address from, address to, uint256 tokenId) external; event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); }
tokenId
solidity interface IERC721 { function ownerOf(uint256 tokenId) external view returns (address); function safeTransferFrom(address from, address to, uint256 tokenId) external; event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); }
ERC‑1155 – A “multi‑token” standard that can hold both fungible and non‑fungible assets in one contract, saving gas with batch operations. solidity interface IERC1155 { function balanceOf(address account, uint256 id) external view returns (uint256); function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external; event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); }
solidity interface IERC1155 { function balanceOf(address account, uint256 id) external view returns (uint256); function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external; event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); }
approve / allowance pattern – Enables a third‑party (e.g., a DEX router) to move tokens on a user’s behalf. js // Ethers.js await token.approve(router.address, ethers.utils.parseUnits("1000", 18));
allowance
js // Ethers.js await token.approve(router.address, ethers.utils.parseUnits("1000", 18));
safeTransferFrom – ERC‑721/1155 function that checks the recipient implements the ERC‑721/1155 receiver interface, preventing tokens from being locked in contracts that can’t handle them.
safeTransferFrom
Metadata URI – ERC‑721 and ERC‑1155 expose tokenURI(uint256) or uri(uint256) that points to off‑chain JSON (IPFS, Arweave) describing the asset.
tokenURI(uint256)
uri(uint256)
supportsInterface(bytes4) – ERC‑165 method that lets contracts announce which ERC standards they implement (e.g., 0x80ac58cd for ERC‑721).
supportsInterface(bytes4)
0x80ac58cd
Batch Minting – ERC‑1155 lets you mint many token IDs in one transaction, cutting gas from ~50 k per NFT to ~5 k for a batch of 10.
transfer vs transferFrom – transfer moves your own tokens; transferFrom moves tokens you’ve been approved for.
ERC20Burnable – Extension that adds a burn(uint256 amount) function, useful for deflationary tokenomics.
ERC20Burnable
burn(uint256 amount)
ERC721Enumerable – Optional ERC‑721 extension that lets you enumerate all tokens owned by an address (tokenOfOwnerByIndex).
ERC721Enumerable
tokenOfOwnerByIndex
ERC1155Holder – A helper contract that implements the receiver callbacks so your contract can safely hold ERC‑1155 tokens.
ERC1155Holder
bash npx hardhat init npm i @openzeppelin/contracts
solc 0.8.24
bash npx hardhat compile npx hardhat test
js const ERC20 = await ethers.getContractFactory("MyToken"); const token = await ERC20.deploy("MyToken", "MTK", 18); await token.deployed(); console.log("Deployed at:", token.address);
npx hardhat verify --network goerli <address> "MyToken" "MyToken" "MTK" 18
Mistake: Forgetting to implement supportsInterface when adding ERC‑721/1155 extensions. Correction: Call ERC165.supportsInterface in your contract; otherwise marketplaces think the token is non‑compliant and refuse to list it.
supportsInterface
ERC165.supportsInterface
Mistake: Using tx.origin for access control (e.g., require(tx.origin == owner)). Correction: Use msg.sender and OpenZeppelin’s Ownable; tx.origin can be spoofed through a malicious contract, opening a phishing vector.
tx.origin
require(tx.origin == owner)
msg.sender
Ownable
Mistake: Approving an unlimited amount (type(uint256).max) for every token transfer. Correction: Approve only the exact amount needed for the operation; unlimited approvals are a common phishing target on DeFi platforms.
type(uint256).max
Mistake: Ignoring the ERC‑165 identifier when building a custom ERC‑1155 receiver. Correction: Return the correct magic value (0xf23a6e61) in onERC1155Received; otherwise the transfer will revert.
0xf23a6e61
onERC1155Received
Mistake: Minting ERC‑721 tokens without emitting the Transfer event from the zero address. Correction: Use OpenZeppelin’s _safeMint which automatically emits the event; missing the event breaks indexers and wallets.
Transfer
_safeMint
“Explain the difference between call and delegatecall.” – Interviewers want to see you understand that delegatecall runs the callee’s code in the caller’s storage context, a common pattern for upgradeable proxies but a source of re‑entrancy bugs.
call
delegatecall
“When would you choose ERC‑1155 over ERC‑721?” – Expect to discuss batch minting, gas savings, and mixed fungible/non‑fungible collections (e.g., a game where each character (ERC‑721) holds consumable items (ERC‑1155)).
“How does ERC‑777 improve on ERC‑20, and why isn’t it universally adopted?” – Talk about hooks (tokensReceived) and operator granularity, but also note the higher audit surface and limited tooling support.
tokensReceived
“What are the trade‑offs between Optimistic Rollups and ZK‑Rollups for token transfers?” – Mention latency vs. proof‑generation cost, and that ERC‑20 transfers on Optimism are cheap but require a fraud‑proof window, whereas ZK‑Rollups give instant finality but need heavy zk‑SNARK circuits.
Scenario: A contract calls token.transferFrom(msg.sender, address(this), amount) without first checking allowance. Answer: The transaction will revert if the allowance is insufficient. Why: transferFrom internally checks allowance and will fail, protecting the token holder from accidental overspending.
token.transferFrom(msg.sender, address(this), amount)
Scenario: An NFT marketplace lists a token that does not implement ERC721Receiver. Answer: The marketplace’s safeTransferFrom will revert, preventing the NFT from being locked. Why: The ERC‑721 spec requires the recipient contract to return the magic value; otherwise the transfer is considered unsafe.
ERC721Receiver
Scenario: A DeFi protocol uses tx.origin == admin to restrict admin functions. Answer: This is insecure because a malicious contract can trick a user into calling the admin function, making tx.origin equal to the admin’s address. Why: tx.origin reflects the original external account, not the immediate caller, so it can be hijacked via phishing.
tx.origin == admin
ownerOf
safeBatchTransferFrom
unchecked {}
i++
solc >=0.8.20
increaseAllowance
decreaseAllowance
0xbc197c81
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.