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
// 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