• Discover
  • Partner with us
  • Chapters
  • Blog

Learn everything about Scroll

Course Introduction

Web1 and Web2
The Middleman
Blockchain Comes Into Play
Web3 As a New Iteration for Web
Web3 Use Cases
The Architecture of a dApp
The Architecture of Web2 Apps

What is ZKP
Submit Your Homework 1
ZKP Tools: Zk-SNARK
ZkSNARK: Under the Hood (Optional)
ZKP Tools: Zk-STARK
ZkSTARK: Under the Hood (Optional)
Applied ZK: Noir
Applied ZK: Circom
Intro to ZK Development
Quiz 1

Scroll & Ethereum
Submit Your Homework 2

Smart Contract Basic and Remix IDE
Introduction to Solidity
Variables and Data Types
Variables and Data Types - Part 2
Functions and Modifiers
Control Flow
Error Handling
Inheritance
Interface
Smart Contract Demo
Deploying Smart Contract to Scroll
Submit Your Homework 3
Bonus: Oracles

zkEVM
Execution Node
Rollup Node
Prover Network
Rollups
Bridge Contracts
Quiz 2

Submit Your Final Project

In this homework, you'll extend the capabilities of our PayPool smart contract. You'll practice using structs to organize data, enums to represent states, and leverage block timestamps for time-dependent logic.

Key Concepts

  • Structs: Custom data types to group related variables.
  • Enums: Sets of named constants to improve code readability.
  • Block Timestamps: Access the current block's timestamp (block.timestamp) for time-based actions.

Instructions

1.Struct for Deposit Records:

  • Create a struct named DepositRecord:
  • depositor (address)
  • amount (uint256)
  • timestamp (uint256)

2.Enum for Deposit Statuses:

  • Create an enum named DepositStatus:
  • Pending
  • Approved
  • Rejected

3. Modify the PayPool Contract:

3.1.Store Deposit Records:

  • Inside the deposit function:
  • Get the current timestamp (block.timestamp).
  • Create a DepositRecord with the depositor's address, deposited amount, and timestamp.
  • Add this record to an array called depositHistory.

3.2.Manage Statuses:

  • Add a status property (type DepositStatus) to the DepositRecord struct.
  • Initialize new deposits as Pending.
  • Create owner-only functions:
  • approveDeposit(uint256 index) to set a deposit's status to Approved.
  • rejectDeposit(uint256 index) to set a deposit's status to Rejected.

3.3.Retrieve Deposit Data:

  • Create a function: getDepositHistory() public view returns (DepositRecord[] memory) to return the depositHistory array.

Paypool Contract

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;


// Imports
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";


contract PayPool is ReentrancyGuard {
    // Data
    uint public totalBalance;
    address public owner;


    address[] public depositAddresses;
    mapping(address => uint256) public allowances;


    // Events
    event Deposit(address indexed depositer, uint256 amount);
    event AddressAdded(address indexed depositer);
    event AddressRemoved(address indexed depositer);
    event AllowanceGranted(address indexed user, uint amount);
    event AllowanceRemoved(address indexed user);
    event FundsRetrieved(address indexed recepient, uint amount);


    modifier isOwner() {
        require(msg.sender == owner, "Not owner!");
        _;
    }


    modifier gotAllowance(address user) {
        require(hasAllowance(user), "This address has no allowance");
        _;
    }


    modifier canDepositTokens(address depositer) {
        require(canDeposit(depositer), "This address is not allowed to deposit tokens");
        _;
    }


    constructor() payable {
        totalBalance = msg.value;
        owner = msg.sender;
    }


    // Internal functions
    function hasAllowance(address user) internal view returns(bool) {
        return allowances[user] > 0;
    }


    function canDeposit(address depositer) internal view returns(bool) {
        for (uint i = 0; i < depositAddresses.length; i++) {
            if (depositAddresses[i] == depositer) {
                return true;
            }
        }
        return false;
    }


    // Execute Functions
    function addDepositAddress(address depositer) external isOwner {
        depositAddresses.push(depositer);
        emit AddressAdded(depositer);
    }


    function removeDepositAddress(uint index) external isOwner canDepositTokens(depositAddresses[index]) {
        depositAddresses[index] = address(0);
        emit AddressRemoved(depositAddresses[index]);
    }


    function deposit() external canDepositTokens(msg.sender) payable {
        totalBalance += msg.value;
        emit Deposit(msg.sender, msg.value);
    }


    function retrieveBalance() external isOwner nonReentrant {
        uint balance = totalBalance;
        (bool success, ) = owner.call{value: balance}("");
        require(success, "Transfer failed");
        totalBalance = 0;
        emit FundsRetrieved(owner, balance);
    }


    function giveAllowance(uint amount, address user) external isOwner {
        require(totalBalance >= amount, "There are no enough tokens inside the pool to give allowance");
        allowances[user] = amount;
        unchecked {
            totalBalance -= amount;
        }
        emit AllowanceGranted(user, amount);
    }


    function removeAllowance(address user) external isOwner gotAllowance(user) {
        allowances[user] = 0;
        emit AllowanceRemoved(user);
    }


    function allowRetrieval() external gotAllowance(msg.sender) nonReentrant {
        uint amount = allowances[msg.sender];
        (bool success, ) = msg.sender.call{value: amount}("");
        require(success, "Retrieval failed");
        allowances[msg.sender] = 0;
        emit FundsRetrieved(msg.sender, amount);
    }
}

Homework Checklist

  • [ ] I created a DepositRecord struct.
  • [ ] I added a DepositStatus enum.
  • [ ] I modified the deposit function to store deposit records with timestamps.
  • [ ] I created functions to let the owner approve or reject deposits.
  • [ ] I created a getDepositHistory function to retrieve deposit data.
  • [ ] I rigorously tested my changes in Remix IDE.

After completing the contract, deploy it on Scroll Sepolia testnet and share your github repo below.

Congratulations, now you are a Solidity Developer!

Previous
Next

Lesson discussion

Swap insights and ask questions about “Learn everything about Scroll”.

Enroll to participate
Start the course to unlock the discussion. Enrolling helps us keep conversations relevant to learners.
WebsiteDiscoverPartner with UsBlogEvents
Discover
CoursesCircleRustSoliditySolanaWeb3 FundamentalsBlockchain Basics
CompanyAbout UsBrand GuidelineFAQsTerms of UsePrivacy PolicyGDPR NoticeCookies
Don't miss any update!

Disclaimer: The information, programs, and events provided on https://risein.com is strictly for upskilling and networking purposes related to the technical infrastructure of blockchain platforms. We do not provide financial or investment advice, nor do we make any representations regarding the value, profitability, or future price of any blockchain or cryptocurrency. Users are encouraged to conduct their own research and consult with licensed financial professionals before engaging in any investment activities. https://risein.com disclaims any responsibility for financial decisions made by users based on the information provided here.

© 2026 Rise In, All rights reserved