Skip to main content

Staking Pattern

Ethereum allows a Dev to create a simple set of rules that an adversarial group of players can use to work together.

  • Coordinate a group funding effort.
  • If the users cooperate
    • money is collected in a second smart contract
  • If users defect
    • the worst that can happen is everyone gets their money back.

The users only have to trust the code.

Scaffold Eth Challenge

Instructions

Create a contract with:

  • Collect money from multiple addresses with a payable function
  • After a deadline
    • if threshold of ETH has been reached
      • send the balance to another contract
      • trigger the complete function
    • if not reached allow users to withdraw

Challenge Overview

ChecksDoneNotes
Staking: track user transfers/balancesX
State Machine & Timing-
Improve Receive Function UX-
Investigate Edge Cases-
Mitigate Traps-
Deploy and Validate-

Checkpoint: 🥩 Staking

Collect funds in a payable stake() function to track account balances using mapping.

note

make sure to add a Stake(address,uint256) event and emit it for the frontend

Goals

[x] Do you see the balance of the Staker contract go up when you stake()? [x] Is your balance correctly tracked? [x] Do you see the events in the Staker UI tab?

Checkpoint: 🔬 State Machine / Timing

Solidity Lang - State Machine

At certain stages a contract may behave differently or allow different functions to be called. Function calls often:

  • end one stage
  • transition into the next
  • state can changes occur automatically at a certain point in time

State changes of a blind auction

  1. accepting blinded bids
  2. revealing bids
  3. determine auction outcome

Function modifiers can be used to enforce state rules

In this exaample the state changes are:

  1. Staking: Active
  2. Success: Enough funds staked
  3. Withdraw: Deadline for funding has passed
tip

Smart contracts can't execute automatically. So you need to create function that can be called externally, that control logic to use dependent on the current state of the contract.

Set a deadline for when when the contract can be checked for sufficient funds.

uint256 public deadline = block.timestamp + 30 seconds;

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?

Questions

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?

Checkpoint: 💵 Receive Function / UX

Improve the user experience, set your contract up so it accepts ETH sent to it and calls stake()

Best Practice

Always ensure there is a Receive function that accepts ETH sent to the contract.

Side Quest: Investigate Edge Cases

  • If you send ETH directly to the contract address does it update your balance?
  • 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?

Traps

  • 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.

Contract Testing

TODO: add more tests for these scenarios above.

Checkpoint 7: Deploy and Verify

See Web3 Deploy

caution

Remember to update all the account settings!!!

caution

Be sure to set your deadline to at least block.timestamp + 72 hours

Results

Etherscan

https://rinkeby.etherscan.io/address/0x8103919C1612bACCf55fC10d96b7756498E58170

App

https://ashamed-tray.surge.sh/

New Deploy

https://rinkeby.etherscan.io/address/0x380a51F75248baaBc97Bc17Fc06beb8a1ef54518
https://apathetic-sun.surge.sh/