π§ͺ An open-source, up-to-date toolkit for building decentralized applications (dapps) on the Ethereum blockchain. It's designed to make it easier for developers to create and deploy smart contracts and build user interfaces that interact with those contracts.
βοΈ Built using NextJS, RainbowKit, Hardhat, Wagmi, Viem, and Typescript.
- β Contract Hot Reload: Your frontend auto-adapts to your smart contract as you edit it.
- πͺ Custom hooks: Collection of React hooks wrapper around wagmi to simplify interactions with smart contracts with typescript autocompletion.
- π§± Components: Collection of common web3 components to quickly build your frontend.
- π₯ Burner Wallet & Local Faucet: Quickly test your application with a burner wallet and local faucet.
- π Integration with Wallet Providers: Connect to different wallet providers and interact with the Ethereum network.
Before you begin, you need to install the following tools:
- Node (>= v20.18.3)
- Yarn (v1 or v2+)
- Git
π€ Smart contracts are kind of like "always on" vending machines that anyone can access. Let's make a decentralized, digital currency. Then, let's build an unstoppable vending machine that will buy and sell the currency. We'll learn about the "approve" pattern for ERC20s and how contract to contract interactions work.
π΅ Create YourToken.sol
smart contract that inherits the ERC20 token standard from OpenZeppelin. Set your token to _mint()
1000 (* 10 ** 18) tokens to the msg.sender
. Then create a Vendor.sol
contract that sells your token using a payable buyTokens()
function.
π Edit the frontend that invites the user to input an amount of tokens they want to buy. We'll display a preview of the amount of ETH it will cost with a confirm button.
π It will be important to verify your token's source code in the block explorer after you deploy. Supporters will want to be sure that it has a fixed supply and you can't just mint more.
π The final deliverable is an app that lets users purchase your ERC20 token, transfer it, and sell it back to the vendor. Deploy your contracts on your public chain of choice and then yarn vercel
your app to a public web server. Submit the url on SpeedRunEthereum.com!
π¬ Meet other builders working on this challenge and get help in the Challenge Telegram!
Start your local network (a blockchain emulator in your computer):
yarn chain
in a second terminal window, π° deploy your contract (locally):
yarn deploy
in a third terminal window, start your π± frontend:
yarn start
π± Open http://localhost:3000 to see the app.
π©βπ» Rerun
yarn deploy
whenever you want to deploy new contracts to the frontend. If you haven't made any contract changes, you can runyarn deploy --reset
for a completely fresh deploy.
π©βπ» Edit
YourToken.sol
to inherit the ERC20 token standard from OpenZeppelin
Mint 1000 (* 10 ** 18) to your frontend address using the
constructor()
.
(Your frontend address is the address in the top right of http://localhost:3000)
You can
yarn deploy --reset
to deploy your contract until you get it right.
- Can you check the
balanceOf()
your frontend address in theDebug Contracts
tab? (YourToken
contract) - Can you
transfer()
your token to another account and check that account'sbalanceOf
?
π¬ Hint: Use an incognito window to create a new address and try sending to that new address. Can use the
transfer()
function in theDebug Contracts
tab.
π©βπ» Edit the
Vendor.sol
contract with a payablebuyTokens()
function
Use a price variable named tokensPerEth
set to 100:
uint256 public constant tokensPerEth = 100;
π The
buyTokens()
function inVendor.sol
should usemsg.value
andtokensPerEth
to calculate an amount of tokens toyourToken.transfer()
tomsg.sender
.
π Emit event
BuyTokens(address buyer, uint256 amountOfETH, uint256 amountOfTokens)
when tokens are purchased.
Edit packages/hardhat/deploy/01_deploy_vendor.ts
to deploy the Vendor
(uncomment Vendor deploy lines).
Uncomment the Buy Tokens
sections in packages/nextjs/app/token-vendor/page.tsx
to show the UI to buy tokens on the Token Vendor tab.
- When you try to buy tokens from the vendor, you should get an error: 'ERC20InsufficientBalance'
βοΈ Side Quest: send tokens from your frontend address to the Vendor contract address and then try to buy them.
βοΈ We can't hard code the vendor address like we did above when deploying to the network because we won't know the vendor address at the time we create the token contract.
βοΈ So instead, edit
YourToken.sol
to mint the tokens to themsg.sender
(deployer) in the constructor().
βοΈ Then, edit
deploy/01_deploy_vendor.ts
to transfer 1000 tokens to vendor address.
await yourToken.transfer(vendorAddress, hre.ethers.parseEther("1000"));
π Look in
packages/nextjs/app/token-vendor/page.tsx
for code to uncomment to display the Vendor ETH and Token balances.
You can
yarn deploy --reset
to deploy your contract until you get it right.
- Does the
Vendor
address start with abalanceOf
1000 inYourToken
on theDebug Contracts
tab? - Can you buy 10 tokens for 0.1 ETH?
- Can you transfer tokens to a different account?
π Edit
Vendor.sol
to inherit Ownable.
contract Vendor is Ownable {
π Change constructor of
Vendor.sol
to:
constructor(address tokenAddress) Ownable(msg.sender) {
In deploy/01_deploy_vendor.ts
you will need to call transferOwnership()
on the Vendor
to make your frontend address the owner
:
await vendor.transferOwnership("**YOUR FRONTEND ADDRESS**");
- Is your frontend address the
owner
of theVendor
?
π Finally, add a
withdraw()
function inVendor.sol
that lets the owner withdraw all the ETH from the vendor contract.
- Can only the
owner
withdraw the ETH from theVendor
?
- What if you minted 2000 and only sent 1000 to the
Vendor
?
π©βπ« The hardest part of this challenge is to build your Vendor
to buy the tokens back.
π§ The reason why this is hard is the approve()
pattern in ERC20s.
π First, the user has to call approve()
on the YourToken
contract, approving the Vendor
contract address to take some amount of tokens.
π€¨ Then, the user makes a second transaction to the Vendor
contract to sellTokens(uint256 amount)
.
π€ The Vendor
should call yourToken.transferFrom(msg.sender, address(this), theAmount)
and if the user has approved the Vendor
correctly, tokens should transfer to the Vendor
and ETH should be sent to the user.
π Edit
Vendor.sol
and add asellTokens(uint256 amount)
function!
approve()
before calling sellTokens(uint256 amount)
.
π¨ Use the Debug Contracts
tab to call the approve and sellTokens() at first but then...
π Look in the packages/nextjs/app/token-vendor/page.tsx
for the extra approve/sell UI to uncomment!
- Can you sell tokens back to the vendor?
- Do you receive the right amount of ETH for the tokens?
-
Should we disable the
owner
withdraw to keep liquidity in theVendor
? -
It would be a good idea to display Sell Token Events. Create an event
SellTokens(address seller, uint256 amountOfTokens, uint256 amountOfETH)
andemit
it in yourVendor.sol
and uncommentSellTokens Events
section in yourpackages/nextjs/app/events/page.tsx
to update your frontend.
- Now is a good time to run
yarn test
to run the automated testing function. It will test that you hit the core checkpoints. You are looking for all green checkmarks and passing tests!
π‘ Edit the defaultNetwork
to your choice of public EVM networks in packages/hardhat/hardhat.config.ts
π You will need to generate a deployer address using yarn generate
This creates a mnemonic and saves it locally.
π©βπ Use yarn account
to view your deployer account balances.
β½οΈ You will need to send ETH to your deployer address with your wallet, or get it from a public faucet of your chosen network.
π Run yarn deploy
to deploy your smart contract to a public network (selected in hardhat.config.ts
)
π¬ Hint: You can set the
defaultNetwork
inhardhat.config.ts
tosepolia
oroptimismSepolia
OR you canyarn deploy --network sepolia
oryarn deploy --network optimismSepolia
.
βοΈ Edit your frontend config in packages/nextjs/scaffold.config.ts
to change the targetNetwork
to chains.sepolia
(or chains.optimismSepolia
if you deployed to OP Sepolia)
π» View your frontend at http://localhost:3000 and verify you see the correct network.
π‘ When you are ready to ship the frontend app...
π¦ Run yarn vercel
to package up your frontend and deploy.
You might need to log in to Vercel first by running
yarn vercel:login
. Once you log in (email, GitHub, etc), the default options should work.
If you want to redeploy to the same production URL you can run
yarn vercel --prod
. If you omit the--prod
flag it will deploy it to a preview/test URL.
Follow the steps to deploy to Vercel. It'll give you a public URL.
π¦ Since we have deployed to a public testnet, you will now need to connect using a wallet you own or use a burner wallet. By default π₯
burner wallets
are only available onhardhat
. You can enable them on every chain by settingonlyLocalBurnerWallet: false
in your frontend config (scaffold.config.ts
inpackages/nextjs/
)
By default, π Scaffold-ETH 2 provides predefined API keys for popular services such as Alchemy and Etherscan. This allows you to begin developing and testing your applications more easily, avoiding the need to register for these services. This is great to complete your SpeedRunEthereum.
For production-grade applications, it's recommended to obtain your own API keys (to prevent rate limiting issues). You can configure these at:
-
π·
ALCHEMY_API_KEY
variable inpackages/hardhat/.env
andpackages/nextjs/.env.local
. You can create API keys from the Alchemy dashboard. -
π
ETHERSCAN_API_KEY
variable inpackages/hardhat/.env
with your generated API key. You can get your key here.
π¬ Hint: It's recommended to store env's for nextjs in Vercel/system env config for live apps and use .env.local for local testing.
Run the yarn verify --network your_network
command to verify your contracts on etherscan π°
π You may see an address for both YourToken and Vendor. You will want the Vendor address.
π Search this address on Sepolia Etherscan (or Optimism Sepolia Etherscan if you deployed to OP Sepolia) to get the URL you submit to πββοΈSpeedRunEthereum.com.
π Head to your next challenge here.
π¬ Problems, questions, comments on the stack? Post them to the π scaffold-eth developers chat
Visit our docs to learn how to start building with Scaffold-ETH 2.
To know more about its features, check out our website.
We welcome contributions to Scaffold-ETH 2!
Please see CONTRIBUTING.MD for more information and guidelines for contributing to Scaffold-ETH 2.