[HELP] Contracts gass and functions

Dear Community this is one of my first complex contracts that I work for a client and yes I'm a complete noob and i wanted to see if anyone could help me check it out, I have been testing it, but Metamask tells me that it can't determine the gass.

When I deploy the contract, everything deploy as well, but when it comes to interacting with the contract, some functions like the sign in function, metaMask tells me that he can’t determine the gas because the contract is wrong and I don’t know how to fix that

I wanted to see if you guys can help me make the contract more efficient or how can I improve it.

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

import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract ProyectRed is ReentrancyGuard, Pausable, Ownable {
    using SafeMath for uint256;

    uint256 public signingFee;
    mapping(address => bool) public hasPaid;
    mapping(address => address) public inviters;
    mapping(address => bool) public blacklisted;
    address payable public externalWallet;
    address payable public investmentWallet;

    uint256 public level1Percentage = 10;
    uint256 public level2Percentage = 5;
    uint256 public level3Percentage = 2;
    uint256 public gratitudeBonusPercentage = 5;

    enum LockPeriod { FOUR_MONTHS, EIGHT_MONTHS, TWELVE_MONTHS }
    struct Investment {
        uint256 amount;
        uint256 payout;
        uint256 startTime;
        LockPeriod period;
    }
    mapping(address => Investment) public investments;
    mapping(address => uint256) public gratitudeBonuses;
    mapping(address => uint256) public lastBonusWithdrawal;

    event FeePaid(address indexed payer, uint256 amount);
    event InviterRegistered(address indexed invitee, address indexed inviter);
    event Invested(address indexed investor, uint256 amount, LockPeriod period);
    event Withdrawn(address indexed investor, uint256 amount);
    event Reinvested(address indexed investor, uint256 amount, LockPeriod period);
    event GratitudeBonusAccrued(address indexed inviter, uint256 amount);
    event GratitudeBonusWithdrawn(address indexed inviter, uint256 amount);

    modifier hasPaidFee() {
        require(hasPaid[msg.sender], "Fee not paid");
        _;
    }

   constructor(uint256 _signingFee, address payable _externalWallet, address payable _investmentWallet) {
        signingFee = _signingFee;
        externalWallet = _externalWallet;
        investmentWallet = _investmentWallet;
    }

    modifier notBlacklisted() {
        require(!blacklisted[msg.sender], "You are blacklisted!");
        _;
    }

    function pauseContract() external onlyOwner {
        _pause();
    }

    function unpauseContract() external onlyOwner {
        _unpause();
    }

    function blacklistAddress(address _address) external onlyOwner {
        blacklisted[_address] = true;
    }

    function unblacklistAddress(address _address) external onlyOwner {
        blacklisted[_address] = false;
    }


     function distributeGratitudeBonus(address _investor, uint256 _investmentAmount) internal {
        address level1 = inviters[_investor];
        if (level1 != address(0)) {
            uint256 bonus = _investmentAmount.mul(gratitudeBonusPercentage).div(100);
            gratitudeBonuses[level1] = gratitudeBonuses[level1].add(bonus);
            emit GratitudeBonusAccrued(level1, bonus);
        }
    }

    function withdrawGratitudeBonus() external nonReentrant whenNotPaused notBlacklisted {
        uint256 bonus = availableGratitudeBonus(msg.sender);
        require(bonus > 0, "No gratitude bonus available or not yet time to withdraw");
        gratitudeBonuses[msg.sender] = gratitudeBonuses[msg.sender].sub(bonus);
        lastBonusWithdrawal[msg.sender] = block.timestamp;
        payable(msg.sender).transfer(bonus);
        emit GratitudeBonusWithdrawn(msg.sender, bonus);
    }

    function availableGratitudeBonus(address _inviter) public view returns (uint256) {
        if (lastBonusWithdrawal[_inviter].add(30 days) <= block.timestamp) {
            return gratitudeBonuses[_inviter];
        }
        return 0;
    }

    function paySigningFee(address _inviter) external payable whenNotPaused notBlacklisted {
        require(msg.value == signingFee, "Incorrect fee sent");
        require(!hasPaid[msg.sender], "Already paid");
        hasPaid[msg.sender] = true;

        if (_inviter != address(0) && hasPaid[_inviter]) {
            inviters[msg.sender] = _inviter;
            distributeRewards(msg.sender);
        }

        uint256 remaining = signingFee - (msg.value * (level1Percentage + level2Percentage + level3Percentage) / 100);
        externalWallet.transfer(remaining);

        emit FeePaid(msg.sender, msg.value);
    }

    function distributeRewards(address _invitee) internal {
        address level1 = inviters[_invitee];
        if (level1 != address(0)) {
            payable(level1).transfer(signingFee * level1Percentage / 100);

            address level2 = inviters[level1];
            if (level2 != address(0)) {
                payable(level2).transfer(signingFee * level2Percentage / 100);

                address level3 = inviters[level2];
                if (level3 != address(0)) {
                    payable(level3).transfer(signingFee * level3Percentage / 100);
                }
            }
        }
    }

    function invest(uint256 _amount, LockPeriod _period) external hasPaidFee whenNotPaused notBlacklisted payable {
        require(msg.value == _amount, "Incorrect amount sent");
        require(investments[msg.sender].amount == 0, "Already invested");

        uint256 multiplier;
        if (_period == LockPeriod.FOUR_MONTHS) {
            multiplier = 12155; // 1.2155 * 10^4 to handle decimals
        } else if (_period == LockPeriod.EIGHT_MONTHS) {
            multiplier = 15938; // 1.5938 * 10^4
        } else if (_period == LockPeriod.TWELVE_MONTHS) {
            multiplier = 22522; // 2.2522 * 10^4
        }

        uint256 payout = _amount * multiplier / 10**4;

        investments[msg.sender] = Investment({
            amount: _amount,
            payout: payout,
            startTime: block.timestamp,
            period: _period
        });

        investmentWallet.transfer(_amount);

        emit Invested(msg.sender, _amount, _period);
    }

    function withdraw(uint256 _amount) external whenNotPaused notBlacklisted {
        Investment storage userInvestment = investments[msg.sender];
        require(userInvestment.amount > 0, "No investment found");
        require(block.timestamp >= getUnlockTime(userInvestment), "Investment still locked");
        require(_amount <= userInvestment.payout, "Withdrawal amount exceeds allowed amount");

        userInvestment.payout -= _amount;
        payable(msg.sender).transfer(_amount);

        emit Withdrawn(msg.sender, _amount);
    }

    function reinvest(uint256 _amount, LockPeriod _period) external whenNotPaused notBlacklisted {
        Investment storage userInvestment = investments[msg.sender];
        require(userInvestment.amount > 0, "No investment found");
        require(block.timestamp >= getUnlockTime(userInvestment), "Investment still locked");
        require(_amount <= userInvestment.payout, "Reinvestment amount exceeds allowed amount");

        uint256 multiplier;
        if (_period == LockPeriod.FOUR_MONTHS) {
            multiplier = 12155; // 1.2155 * 10^4 to handle decimals
        } else if (_period == LockPeriod.EIGHT_MONTHS) {
            multiplier = 15938; // 1.5938 * 10^4
        } else if (_period == LockPeriod.TWELVE_MONTHS) {
            multiplier = 22522; // 2.2522 * 10^4
        }

        uint256 payout = _amount * multiplier / 10**4;

        userInvestment.amount += _amount;
        userInvestment.payout += payout - _amount; // Subtract the reinvested amount
        userInvestment.startTime = block.timestamp;
        userInvestment.period = _period;

        emit Reinvested(msg.sender, _amount, _period);
    }

    function getUnlockTime(Investment memory _investment) public pure returns (uint256) {
        if (_investment.period == LockPeriod.FOUR_MONTHS) {
            return _investment.startTime + 4 * 30 days;
        } else if (_investment.period == LockPeriod.EIGHT_MONTHS) {
            return _investment.startTime + 8 * 30 days;
        } else if (_investment.period == LockPeriod.TWELVE_MONTHS) {
            return _investment.startTime + 12 * 30 days;
        }
        return 0;
    }

    function setSigningFee(uint256 _newFee) external onlyOwner {
        signingFee = _newFee;
    }

    function setExternalWallet(address payable _newWallet) external onlyOwner {
        externalWallet = _newWallet;
    }

    function setInvestmentWallet(address payable _newWallet) external onlyOwner {
        investmentWallet = _newWallet;
    }

    function setPercentages(uint256 _level1, uint256 _level2, uint256 _level3) external onlyOwner {
        level1Percentage = _level1;
        level2Percentage = _level2;
        level3Percentage = _level3;
    }

        function setGratitudeBonusPercentage(uint256 _percentage) external onlyOwner {
        gratitudeBonusPercentage = _percentage;
    }

 // Fallback and receive functions
    fallback() external payable {
        revert("Please use the appropriate function to interact with the contract.");
    }

    receive() external payable {
        revert("Please use the appropriate function to interact with the contract.");
    }
}


Hey,
First of all I would say, please mention the failing part, like, is the deployment stuck, or a particular function?

Secondly you don't need SafeMath if you are using solidity version above 0.8.0, it already has an inbuilt check for overflow and underflow. SafeMath will add no value but some gas cost.

1 Like

Thank you so much for your support, the thing is that when I deploy the contract it deploy as well, but when I want to start interacting with it, MetaMask spits out an error, but it can’t determine the gas. I don’t know if it’s a contract or something that I need to change in the functions of the contract

All of the functions are failing?
Share the deployed contract address.

1 Like

0x08bf4D42e42F887Ca28e3CdA9d7BB2C7D82b6A91