Introduction
In this guide, we’ll explore the first scaffold-ETH learning project: creating a staking dApp inspired by Ethereum 2.0’s staking contract.
Key Objectives
- Allow users to stake ETH and track balances.
- Prevent withdrawals once a deadline is reached or the staking threshold is met (funds are locked for future use, e.g., Ethereum POS).
What You’ll Learn
- Setting up a scaffold-ETH project.
- Writing a staking contract in Solidity.
- Interacting with external contracts.
- Creating unit tests for your contract.
- Testing locally with React.
- Deploying the contract to an Ethereum testnet.
Essential Resources
- Solidity Examples
- Solidity Documentation
- Hardhat Documentation
- Ethers.js Documentation
- OpenZeppelin Docs
Project Setup
Clone and Configure
Clone the scaffold-eth repository:
git clone https://github.com/austintgriffith/scaffold-eth.git challenge-1-decentralized-staking cd challenge-1-decentralized-staking git checkout challenge-1-decentralized-staking yarn install
Key Commands
Local Development:
yarn chain # Starts Hardhat network (http://localhost:8545) yarn start # Launches React app (http://localhost:3000) yarn deploy # Deploys contracts and refreshes the app
Part 1: Implementing the stake()
Function
Core Concepts
- Payable Functions: Allow ETH transfers.
- Mappings: Track user balances (
address => uint256
). - Events: Emit notifications for on-chain actions (e.g.,
Stake
).
Code Implementation
Update Staker.sol
:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "hardhat/console.sol";
import "./ExampleExternalContract.sol";
contract Staker {
ExampleExternalContract public exampleExternalContract;
mapping(address => uint256) public balances;
uint256 public constant threshold = 1 ether;
event Stake(address indexed sender, uint256 amount);
constructor(address exampleExternalContractAddress) {
exampleExternalContract = ExampleExternalContract(exampleExternalContractAddress);
}
function stake() public payable {
balances[msg.sender] += msg.value;
emit Stake(msg.sender, msg.value);
}
}
Testing Your Contract
- Deploy the contract.
- Fund your wallet via the Faucet.
- Stake ETH (e.g., 0.5 ETH).
Verify:
- Balances update correctly.
- Events trigger in the UI.
- Contract balance reflects the stake.
FAQs
Q: Why isn’t my balance updating?
A: Ensure stake()
is called with msg.value > 0
and the transaction succeeds.
Q: What’s the purpose of the threshold
?
A: It’s the cap for total staked ETH (e.g., 1 ETH).
Q: How do I test events?
A: Check the browser console or use tools like Etherscan for testnets.
This guide continues in Part 2, where we’ll cover withdrawal logic and external contract interactions. Stay tuned!