In this guide, we will explore how to build a decentralized staking application (dApp) using the scaffold-eth framework. This initial project is designed to help developers understand the fundamentals of smart contract development, testing, and deployment on Ethereum-compatible networks.
What is a Staking dApp?
A staking dApp allows users to lock their cryptocurrency assets, such as ETH, into a smart contract for a specified period. In return, users may earn rewards or contribute to network security. The goal of this project is to create a simplified version of a staking contract that mimics some aspects of Ethereum 2.0’s staking mechanism.
Key features of the staking dApp include:
- Allowing users to stake ETH and track their balances.
- Implementing a deadline or threshold that prevents withdrawals once certain conditions are met.
What You Will Learn
This tutorial will help you gain practical experience in:
- Setting up a scaffold-eth development environment.
- Writing and testing a Solidity staking contract.
- Interacting with external contracts.
- Creating unit tests for your smart contracts.
- Deploying contracts to a testnet.
This project serves as an excellent starting point for developers new to Ethereum development.
Prerequisites and Useful Resources
Before starting, ensure you are familiar with:
- Basic Solidity syntax and smart contract structure.
- JavaScript and React for front-end integration.
- Using Hardhat or Truffle for development environments.
Here are some recommended resources for further learning:
- Solidity by Example
- Official Solidity Documentation
- Hardhat Documentation
- Ethers.js Documentation
- OpenZeppelin Contracts
Setting Up the Scaffold-ETH Project
To begin, clone the scaffold-eth repository and install the necessary dependencies:
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
Overview of CLI Commands
Scaffold-eth provides several useful commands for development:
yarn chain
– Starts a local Hardhat network at http://localhost:8545.yarn start
– Launches the React front-end at http://localhost:3000.yarn deploy
– Deploys contracts and updates the React app.
For an efficient workflow, open three separate terminals to run these commands simultaneously. After modifying your contract, simply rerun the deploy command to apply changes.
Implementing the Stake Function
In this section, we will implement a stake()
function that allows users to deposit ETH and update their balances.
Key Concepts
- Payable Functions: Functions marked as
payable
can receive ETH. This is essential for handling staking transactions. - Mappings: Used to store key-value pairs, such as user addresses and their staked balances.
- Events: Emit notifications for off-chain applications to track on-chain activities, like deposits.
Implementation Steps
- Declare a mapping to track user balances.
- Set a constant threshold (e.g., 1 ETH).
- Define a
Stake
event to log staking transactions. - Write a
stake()
function that updates the user’s balance and emits the event.
Here is an example implementation:
// 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);
}
}
Notes on the Code
uint256
is interchangeable withuint
(it is an alias).- Public variables automatically generate getter functions.
- Uninitialized variables are set to their default values (e.g., 0 for
uint256
). - Solidity provides built-in units like
ether
andwei
for value handling.
Testing the Implementation
After deploying your contract, test the following:
- Obtain test ETH from a faucet.
- Stake 0.5 ETH using the
stake()
function. - Verify that the event is emitted and recorded.
- Check that the user balance and contract balance update correctly.
👉 Explore more staking strategies
Frequently Asked Questions
What is scaffold-eth?
Scaffold-eth is a development framework that simplifies Ethereum dApp creation. It provides pre-configured environments for writing, testing, and deploying smart contracts.
Why use mappings for balances?
Mappings are efficient for tracking address-based data, such as user balances. They provide constant-time lookup and are ideal for this use case.
How do payable functions work?
Payable functions can accept ETH sent with transactions. This is critical for staking, deposits, and other value-transfer operations.
What are events used for?
Events emit logs that are stored on the blockchain and can be read by off-chain applications. They are useful for tracking contract activity.
How can I test my contract?
Use Hardhat’s testing environment to write unit tests. You can simulate transactions and verify contract behavior without deploying to a live network.
What is the purpose of the threshold?
The threshold defines a limit for staking or withdrawal conditions. In this project, it prevents withdrawals once the total staked amount reaches 1 ETH.
Next Steps
Once you have successfully implemented and tested the stake()
function, proceed to part two of this tutorial. You will learn how to add withdrawal functionality, implement time-based conditions, and integrate with external contracts.
This project provides a solid foundation for building more complex dApps and understanding Ethereum’s staking mechanisms. Happy coding!