Prompt Web3
  • 🤓Web3 Refresher Course with GptTutor
  • Creating your own Custom personas
  • Creating The Web3 GptTutor
  • Prompting the course sylibus
  • Prompting new lessons
  • Expanding parts of a lesson
  • Lesson 1
    • Lesson 1: Outline
    • Lesson 1: Assignments & Exercises
      • A1: Smart contracts in the real world
      • E1: HelloWorld.sol
  • Lesson 2
    • Lesson 2: Outline
    • Lesson 2: Assignments & Exercises
      • A1: Ethereum gas costs, data types and control structures - A brief take
      • E1: AssetManagement.sol
    • Lesson 2: Final notes and code repos
  • Lesson 3
    • Lesson 3: Outline
    • Lesson 3: Assignments & Excercises
      • A1 - Notes on View and Pure modifiers in Solidity
      • E1: EthWallet.sol
      • E1: Hardhat Tests
      • E1: NextJs Front End
    • Lesson 3: Final notes & Final project + repo
  • Lesson 4
    • Lesson 4: Outline
    • Lesson 4: Assignments & Exercises
      • A1 - Solidity error handling - notes on require, revert and assert
      • E1: EthWallet.sol - Update
      • E1 - EthWallet.test.js - Update
      • E1: NextJs Front End - Update
    • Lesson 4: Final notes & Final project + repo
  • Lesson 5
    • Lesson 5: Outline
    • Lesson 5: Assignments & Exercises
      • A1 - Using structs and mappings to manage complex data in Solidity
      • E1 - OrderSystem.sol
      • E1 - OrderSystem.test.js
    • Lesson 5: Final notes & Project Repo
  • LESSON 6
    • Lesson 6: Outline
    • Lesson 6: Assignments & Exercises
      • A1 - Solidity Interfaces - Facilitating interaction, modularity and Dapp upgradability
      • E1 - Ranked Choice Voting system
        • E1 - BallotContract.sol
        • E1 - IBallotContract.sol
        • E1 - VotingContract.sol
        • E1 - RCVotingSystem.test.js
      • E1 - Feedback
    • Lesson 6: Final notes & Project Repo
  • Lesson 7
    • Lesson 7: Outline
    • Lesson 7: Assignments & Exercises
      • E1 - Uniswap Flashswap dual Arbitrage Bot
        • E1 - FlashSwapV3.sol
        • E1 - dualArbScan.js
        • E1 - arbQuote.js
      • Lesson 7: Final notes & Project Repo
Powered by GitBook
On this page
  1. Lesson 4
  2. Lesson 4: Assignments & Exercises

E1: EthWallet.sol - Update

Modify the above contract to include events for each deposit and withdrawal action. Test the contract to ensure that events are emitted correctly.

Modifying EthWallet.sol

In this lesson the key differences to the contract are:

  • Gas optimized 'deposit' and 'withdraw' functions

  • Events added for both functions.

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/* errors */
error EthWallet__DepositMustBeAboveZero();
error EthWallet__WithdrawalMustBeAboveZero();
error EthWallet__WalletIsEmpty();
error EthWallet__WithdrawalExceedsUserBalance();
error EthWallet_InsufficientContractBalance();

// ----------------- Events added ---------------------

/* events */
event DepositSuccess(address depositer, uint amount);
event WithdrawSuccess(address withdrawer, uint amount);

// ----------------------------------------------------

contract EthWallet {
    /* structs */
    struct User {
        address ownerAddress;
        uint userBalance;
        uint withdrawnToday;
        uint lastWithdrawalTime;
    }

    /* mappings */
    mapping(address => User) private users;

    /* state variables */
    uint public constant dailyWithdrawalLimit = 10 ether;
    bool private locked;
    uint currentBalance;

    modifier withdrawalLimitCheck(uint _withdrawalAmount) {
        User storage currentUser = users[msg.sender];

        // Reset withdrawal amount if a new day has started
        if (isNewDay(currentUser.lastWithdrawalTime)) {
            currentUser.withdrawnToday = 0;
        }

        // Check if the requested withdrawal exceeds the daily limit
        require(
            currentUser.withdrawnToday + _withdrawalAmount <=
                dailyWithdrawalLimit,
            "Daily withdrawal limit exceeded"
        );

        // Update user's withdrawal data
        currentUser.withdrawnToday += _withdrawalAmount;
        currentUser.lastWithdrawalTime = block.timestamp;
        _;
    }

    modifier sufficientBalance(uint _withdrawalAmount) {
        uint withdrawalAmount = _withdrawalAmount;
        currentBalance = users[msg.sender].userBalance;
        if (currentBalance == 0) {
            revert EthWallet__WalletIsEmpty();
        } else if (_withdrawalAmount > address(this).balance) {
            revert EthWallet_InsufficientContractBalance();
        } else if (_withdrawalAmount > currentBalance) {
            revert EthWallet__WithdrawalExceedsUserBalance();
        }
        _;
    }

    modifier noReeentrant() {
        require(!locked, "No re_entrancy");
        locked = true;
        _;
        locked = false;
    }

    // Helper function to determine if a new day has started
    function isNewDay(uint lastWithdrawalTime) internal view returns (bool) {
        uint currentDay = block.timestamp / 1 days;
        uint lastWithdrawalDay = lastWithdrawalTime / 1 days;
        return currentDay > lastWithdrawalDay;
    }

    function deposit() public payable {
    
        // -Require statement replaced custom error for input validation-
        // ---------- 18.3% gas reduction for calculation cost ----------
        
        require(msg.value > 0, "Deposit must be above zero!");
        
        // --------------------------------------------------------------

        uint depositAmount = msg.value;

        if (users[msg.sender].userBalance > 0) {
            users[msg.sender].userBalance += depositAmount;
        } else {
            users[msg.sender] = User(msg.sender, depositAmount, 0, 0);
        }

        emit DepositSuccess(msg.sender, depositAmount);
    }

    function withdraw(
        uint _withdrawalAmount
    )
        external
        withdrawalLimitCheck(_withdrawalAmount)
        sufficientBalance(_withdrawalAmount)
        noReeentrant
    {
    
        // -Require statement replaced custom error for input validation-
        // ---------- 18.3% gas reduction for calculation cost ----------
        
        require(_withdrawalAmount > 0, "Withdrawal must be above zero!");
        
        // --------------------------------------------------------------

        uint withdrawalAmount = _withdrawalAmount;

        // Update user Balance
        users[msg.sender].userBalance -= withdrawalAmount;

        // Process withdrawal
        payable(msg.sender).transfer(withdrawalAmount);

        emit WithdrawSuccess(msg.sender, withdrawalAmount);
    }

    function getUserBalance() public view returns (uint) {
        if (users[msg.sender].ownerAddress != address(0)) {
            return users[msg.sender].userBalance;
        } else {
            return 0;
        }
    }
}
PreviousA1 - Solidity error handling - notes on require, revert and assertNextE1 - EthWallet.test.js - Update

Last updated 1 year ago