๐Ÿฅฉ
Decentralized Staking App
Build a staking dapp ๐Ÿ‘จ๐Ÿผโ€๐Ÿ’ป

๐Ÿšฉ Challenge 1: ๐Ÿฅฉ Decentralized Staking App

๐Ÿฆธ A super power of Ethereum is allowing you, the builder, to create a simple set of rules that an adversarial group of players can use to work together. In this challenge, you create a decentralized application where users can coordinate a group funding effort. If the users cooperate, the money is collected in a second smart contract. If they defect, the worst that can happen is everyone gets their money back. The users only have to trust the code.
๐Ÿฆ Build a Staker.sol contract that collects ETH from numerous addresses using a payable stake() function and keeps track of balances. After some deadline if it has at least some threshold of ETH, it sends it to an ExampleExternalContract and triggers the complete() action sending the full balance. If not enough ETH is collected, allow users to withdraw().
๐ŸŽ› Building the frontend to display the information and UI is just as important as writing the contract. The goal is to deploy the contract and the app to allow anyone to stake using your app. Use a Stake(address,uint256) event to all stakes.
๐Ÿ† The final deliverable is deploying a decentralized application to a public blockchain and then yarn build and yarn surge your app to a public webserver. Share the url in the Challenge 1 telegram channel to earn a collectible and cred! Part of the challenge is making the UI/UX enjoyable and clean! ๐Ÿคฉ
๐Ÿงซ Everything starts by โœ๏ธ Editing Staker.sol in packages/hardhat/contracts
โ€‹

โœ… Checkpoint 0: ๐Ÿ“ฆ Install ๐Ÿ“š

git clone https://github.com/scaffold-eth/scaffold-eth-challenges.git challenge-1-decentralized-staking
โ€‹
cd challenge-1-decentralized-staking
โ€‹
git checkout challenge-1-decentralized-staking
โ€‹
yarn install
๐Ÿ” Edit your smart contract Staker.sol in packages/hardhat/contracts
โ€‹

โœ… Checkpoint 1: ๐Ÿ”ญ Environment ๐Ÿ“บ

You'll have three terminals up for:
yarn start (react app frontend)
yarn chain (hardhat backend)
yarn deploy (to compile, deploy, and publish your contracts to the frontend)
๐Ÿ’ป View your frontend at http://localhost:3000/
๐Ÿ‘ฉโ€๐Ÿ’ป Rerun yarn deploy --reset whenever you want to deploy new contracts to the frontend.
โ€‹

โœ… Checkpoint 2: ๐Ÿฅฉ Staking ๐Ÿ’ต

You'll need to track individual balances using a mapping:
mapping ( address => uint256 ) public balances;
And also track a constant threshold at 1 ether
uint256 public constant threshold = 1 ether;
๐Ÿ‘ฉโ€๐Ÿ’ป Write your stake() function and test it with the Debug Contracts tab in the frontend
๐Ÿฅ… Goals
  • Do you see the balance of the Staker contract go up when you stake()?
  • Is your balance correctly tracked?
  • Do you see the events in the Staker UI tab?
โ€‹

Checkpoint 3: ๐Ÿ”ฌ State Machine / Timing โฑ

โš™๏ธ Think of your smart contract like a state machine. First, there is a stake period. Then, if you have gathered the threshold worth of ETH, there is a success state. Or, we go into a withdraw state to let users withdraw their funds.
Set a deadline of block.timestamp + 30 seconds
uint256 public deadline = block.timestamp + 30 seconds;
๐Ÿ‘จโ€๐Ÿซ . Smart contracts can't execute automatically, you always need to have a transaction execute to change state. Because of this, you will need to have an execute() function that anyone can call, just once, after the deadline has expired.
๐Ÿ‘ฉโ€๐Ÿ’ป Write your execute() function and test it with the Debug Contracts tab
If the address(this).balance of the contract is over the threshold by the deadline, you will want to call: exampleExternalContract.complete{value: address(this).balance}()
If the balance is less than the threshold, you want to set a openForWithdraw bool to true and allow users to withdraw(address payable) their funds.
(You'll have 30 seconds after deploying until the deadline is reached, you can adjust this in the contract.)
๐Ÿ‘ฉโ€๐Ÿ’ป Create a timeLeft() function including public view returns (uint256) that returns how much time is left.
โš ๏ธ Be careful! if block.timestamp >= deadline you want to return 0;
โณ The time will only update if a transaction occurs. You can see the time update by getting funds from the faucet just to trigger a new block.
๐Ÿ‘ฉโ€๐Ÿ’ป You can call yarn deploy --reset any time you want a fresh contract
๐Ÿฅ… Goals
  • Can you see timeLeft counting down in the Staker UI tab when you trigger a transaction with the faucet?
  • If you stake() enough ETH before the deadline, does it call complete()?
  • If you don't stake() enough can you withdraw(address payable) your funds?
โ€‹

โœ… Checkpoint 4: ๐Ÿ’ต Receive Function / UX ๐Ÿ™Ž

๐ŸŽ€ To improve the user experience, set your contract up so it accepts ETH sent to it and calls stake(). You will use what is called the receive() function.
Use the receive() function in solidity to "catch" ETH sent to the contract and call stake() to update balances.
โ€‹
๐Ÿฅ… Goals
  • If you send ETH directly to the contract address does it update your balance?
โ€‹

โš”๏ธ Side Quests

  • Can execute get called more than once, and is that okay?
  • Can you stake and withdraw freely after the deadline, and is that okay?
  • What are other implications of anyone being able to withdraw for someone?
โ€‹

๐Ÿธ It's a trap!

  • Make sure funds can't get trapped in the contract! Try sending funds after you have executed! What happens?
  • Try to create a modifier called notCompleted. It will check that ExampleExternalContract is not completed yet. Use it to protect your execute and withdraw functions.
โ€‹

โœ… Checkpoint 5: ๐Ÿšข Ship it ๐Ÿš

๐Ÿ“ก Edit the defaultNetwork to your choice of public EVM networks in packages/hardhat/hardhat.config.js
๐Ÿ‘ฉโ€๐Ÿš€ You will want to run yarn account to see if you have a deployer address
๐Ÿ” If you don't have one, run yarn generate to create a mnemonic and save it locally for deploying.
โ›ฝ๏ธ You will need to send ETH to your deployer address with your wallet.
๐Ÿš€ Run yarn deploy to deploy your smart contract to a public network (selected in hardhat.config.js)
โ€‹

โœ… Checkpoint 6: ๐ŸŽš Frontend ๐Ÿง˜โ€โ™€๏ธ

๐Ÿ“ Edit the targetNetwork in App.jsx (in packages/react-app/src) to be the public network where you deployed your smart contract.
๐Ÿ’ป View your frontend at http://localhost:3000/
๐Ÿ‘ฉโ€๐ŸŽค Take time to craft your user experience...
๐Ÿ“ก When you are ready to ship the frontend app...
๐Ÿ“ฆ Run yarn build to package up your frontend.
๐Ÿ’ฝ Upload your app to surge with yarn surge (you could also yarn s3 or maybe even yarn ipfs?)
๐Ÿ“ you will use this deploy URL to submit to SpeedRun.
๐Ÿš” Traffic to your url might break the Infura rate limit, edit your key: constants.js in packages/ract-app/src.
๐ŸŽ– Show off your app by pasting the url in the Challenge 1 telegram channelโ€‹
โ€‹

โœ… Checkpoint 7: ๐Ÿ“œ Contract Verification

Update the api-key in packages/hardhat/package.json file. You can get your key here.
Screen Shot 2021-11-30 at 10 21 01 AM
Now you are ready to run the yarn verify --network your_network command to verify your contracts on etherscan ๐Ÿ›ฐ This will be the URL you submit to SpeedRun.
๐Ÿƒ Head to your next challenge here.
๐Ÿ’ฌ Problems, questions, comments on the stack? Post them to the ๐Ÿ— scaffold-eth developers chatโ€‹