mail@pastecode.io avatar
a month ago
3.9 kB
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// Define custom errors
error InvalidAmount(uint256 sent, uint256 minRequired);
error InsufficientBalance(uint256 requestedAmount, uint256 balance);

// Contract: ExternalCheck (check if a balance is sufficient and if an amount is greater than zero in the SmartWallet contract)
contract ExternalCheck {
    // Function to check if the balance is sufficient
    function sufficientBalance(uint256 balance, uint256 amount) public pure {
        require(balance >= amount, "Insufficient balance.");

    // Function to check if the amount is greater than zero
    function validateAmountGreaterThanZero(uint256 amount) public pure {
        require(amount > 0, "Amount must be greater than zero.");

contract SmartWallet {
    // Struct to store user information
    struct User {
        uint256 balance;

    // Mapping to store user balances
    mapping(address => User) users;

    // Minimum required amount
    uint256 minRequired;
    // External contract instance
    ExternalCheck public externalCheck;

    // Events to log deposit, withdrawal, and transfer actions
    event Deposited(address indexed account, uint256 amount);
    event Withdrawn(address indexed account, uint256 amount);
    event Transferred(address indexed from, address indexed to, uint256 amount);

    // Modifier to check if the user exists
    modifier userExists(address user) {
        require(users[user].balance > 0, "User not found.");

    // Modifier to check if the user has a sufficient balance
    modifier sufficientBalance(uint256 amount) {
        require(users[msg.sender].balance >= amount, "Insufficient balance.");

    // Constructor to set the minimum required amount and deploy the external contract
    constructor(uint256 _minRequired) {
        minRequired = _minRequired;
        externalCheck = new ExternalCheck();

    // Function to deposit Ether
    function deposit() public payable {
        // Check if the deposited amount is greater than zero
        // Update the user's balance
        User storage user = users[msg.sender];
        user.balance += msg.value;
        // Emit the Deposited event
        emit Deposited(msg.sender, msg.value);

    // Function to withdraw Ether
    function withdraw(uint256 amount) public payable userExists(msg.sender) {
        User storage user = users[msg.sender];
        // Check if the user has a sufficient balance
        externalCheck.sufficientBalance(user.balance, amount);

        // Deduct the requested amount from the user's balance
        user.balance -= amount;

        // Transfer the requested amount to the user's address
        require(payable(msg.sender).send(amount), "Failed to send Ether.");
        // Emit the Withdrawn event
        emit Withdrawn(msg.sender, amount);

    // Function to transfer Ether from one user to another
    function transfer(uint256 amount, address recipient) public userExists(recipient) userExists(msg.sender) {
        User storage sender = users[msg.sender];
        User storage receiver = users[recipient];

        // Check if the sender has a sufficient balance
        externalCheck.sufficientBalance(sender.balance, amount);

        // Deduct the transferred amount from the sender's balance
        sender.balance -= amount;

        // Add the transferred amount to the receiver's balance
        receiver.balance += amount;

        // Emit the Transferred event
        emit Transferred(msg.sender, recipient, amount);
    // Function to check the balance of the caller
    function checkBalance() public view returns (uint256) {
        // Return the balance of the caller.
        return users[msg.sender].balance;