0

If i remove payable from: enter image description here then i get this error with my receive function. Not sure how to fix this. I have an erc20 token contract that has a receive function and this contract inherits from it, that's why it has override. Another thing to note is that the erc20 contract also has the same problem with delcaring address(this) to a payable address with a receive function.

enter image description here

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

import "./lib/Permissioned.sol";
import "./interfaces/ICredits.sol";

// ----------------------------------------------------------------------------
//
//                      (c) The BotNet Project 2020
//
// ----------------------------------------------------------------------------

// TO DO...
// [ ] ADD PERMISSION MODIFIER W/ "hasAccess" bool variable -> ONLY OBTAINABLE VIA DEPLOYER CONFIRMATION 
// [ ] MAKE APPROVE FUNCTION THAT CONTRACTS WITH PERMISSION CAN ACCESS 

contract Credits is ICredits, Permissioned {
    using SafeMath for uint256;

//  ----------------------------------------------------
//               Variables + Constructor
//  ----------------------------------------------------

    string _name = "Credits";
    string _symbol = "CRDTS";
    uint8 _decimals = 18;                       
    uint256 public initialCreditsSupply = 20000000 * 10**uint(_decimals);         // 20,000,000 credits supply upon deployment
    uint256 private totalCreditsSupply;                                           // Credits' total supply (can be adjusted)
    uint256 public totalCreditsHeld;                                              // how many Credits are in custody of users
    uint256 public remainingUnheldCredits;                                        // amount of credits that aren't owned
    address payable creditsContract;                                              // the address that holds the total supply

    constructor() {    
        isPaused = false;                                                  // contract is unpaused on deployment
        creditsContract = address(this);                                   // creditsContract = this contract address (Credits.sol)    
        users[creditsContract].hasContractAccess = true;                   // is given contract access for contractApprove()
        totalCreditsSupply = initialCreditsSupply;                         // total credits supply = total inital credits supply
        totalCreditsHeld = 0;                                              // credits held by users = 0
        users[creditsContract].creditBalance = totalCreditsSupply;         // creditsContract owns total supply
        remainingUnheldCredits = users[creditsContract].creditBalance;     // amount of credits that aren't owned = total supply
    }

//  ----------------------------------------------------
//                   View Functions 
//  ----------------------------------------------------

    function symbol() override external view returns (string memory) {
        return _symbol;
    }
    function name() override external view returns (string memory) {
        return _name;
    }
    function decimals() override external view returns (uint8) {
        return _decimals;
    }
    function totalSupply() override external view returns (uint) {
        return totalCreditsSupply;  
    }
    function balanceOf(address tokenOwner) override external view returns (uint creditBalance) {
        return users[tokenOwner].creditBalance;
    }

//  ----------------------------------------------------
//                User Transfer Functions 
//  ----------------------------------------------------

    function transfer(address _to, uint _amount) override external pauseFunction returns (bool success) {
        require(users[msg.sender].creditBalance >= _amount, "insufficient funds, revert");
        _transfer(msg.sender, _to, _amount);
        return true;
    }
    
    function transferFrom(address _from, address _to, uint _amount) override external pauseFunction returns (bool success) {
        require(users[_from].creditBalance >= _amount, "from address has insufficient funds, revert");
        require(users[msg.sender].allowance[_from] >= _amount, "insufficient allowance, revert");
        require(users[msg.sender].allowance[_from] <= users[_from].creditBalance);
        users[msg.sender].allowance[_from] = users[msg.sender].allowance[_from].sub(_amount);
        _transfer(_from, _to, _amount);
        return true;
    }

    function _transfer(address _from, address _to, uint256 _amount) private pauseFunction {
        if(_from == creditsContract) {
            users[_from].creditBalance = users[_from].creditBalance.sub(_amount);
            users[_to].creditBalance = users[_to].creditBalance.add(_amount);
            remainingUnheldCredits = users[owner].creditBalance;
            totalCreditsHeld = totalCreditsSupply.add(remainingUnheldCredits);
        } else if (_to == creditsContract){
            users[_from].creditBalance = users[_from].creditBalance.sub(_amount);
            users[_to].creditBalance = users[_to].creditBalance.add(_amount);
            remainingUnheldCredits = users[owner].creditBalance;
            totalCreditsHeld = totalCreditsSupply.sub(remainingUnheldCredits);
        } else {
            users[_from].creditBalance = users[_from].creditBalance.sub(_amount);
            users[_to].creditBalance = users[_to].creditBalance.add(_amount);
        }
        emit Transfer(msg.sender, _to, _amount);
    }

//  ----------------------------------------------------
//               User Approve + Allowance 
//  ----------------------------------------------------

    function contractApprove(address _approver, address _approvee, uint256 _amount) contractAccess external returns (bool success) {
        _approve(_approver, _approvee, _amount);
        return true;
    }

    function approve(address _spender, uint _amount) override external pauseFunction returns (bool success) {
        // require(msg.sender != creditsContract, "ERROR: Unable to set ");
        _approve(msg.sender, _spender, _amount);
        return true;
    }

    function _approve(address _owner, address _spender, uint _amount) private {
        users[_owner].allowance[_spender] = _amount;
        emit Approval(_owner, _spender, _amount);
    }

    function viewAllowance(address tokenOwner, address spender) override external pauseFunction view returns (uint remaining) {
        return users[tokenOwner].allowance[spender];
    }

//  ----------------------------------------------------
//                 Mint + Burn Credits 
//  ----------------------------------------------------

    function generateCredits(uint _amount) override external onlyOwner returns (bool success) {
        users[creditsContract].creditBalance = users[creditsContract].creditBalance.add(_amount);
        totalCreditsSupply = totalCreditsSupply.add(_amount);
        remainingUnheldCredits = users[owner].creditBalance;              
        emit generatedCredits(totalCreditsSupply, creditsContract, _amount);
        return true;
    }
    function deleteCredits(uint _amount) override external onlyOwner returns (bool success) {
        require(users[creditsContract].creditBalance >= _amount);
        users[creditsContract].creditBalance = users[creditsContract].creditBalance.sub(_amount);
        totalCreditsSupply = totalCreditsSupply.sub(_amount);
        remainingUnheldCredits = users[creditsContract].creditBalance;    
        emit deletedCredits(totalCreditsSupply, _amount);
        return true;
    }

    // ------------------------------------------------------------------------
    //                          Don't accept ETH
    // ------------------------------------------------------------------------
    receive () virtual external payable {
        revert();
    }
} 

Note: I was in the middle of changing names of variables, etc so don't mind them. It should be unrelated to the receive function , I think.

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

import "./Credits.sol";

/// @title Inital Token Offering (ITO)
/// @dev ITO is the contract for managing the Credits' crowdsale
// allowing investors to purchase Credits for Ether. 

// TO DO...
// [X] MAKE INTO A SLOW DRIP INSTEAD OF EVERYONE GETS AT ONCE (i.e. 25% at the start of each month for 4 months)
// [X] MAKE TOKENS CLAIMABLE FOR CREDITS  
// [ ] MAKE MODIFIER "SOLD OUT" FOR REMAINING CREDIBYTES REMAINING, THAT ARE ABLE TO BE PURCHASED
// [ ] MAKE A CREDITS TOTAL SUPPLY 
// [ ] FIX TRANSFERFROM & TRANSFER FUNCTION SO DEVS CANT DRAIN SUPPLY

contract CreditsITO is Credits {
  using SafeMath for uint256;

  Credits credits;                                      // The token being sold

  uint256 public conversionRate_EthToCredits;        // How many credibytes a buyer gets per eth.
  uint256 public totalEthRaised;                        // Amount of eth raised
  uint256 public minEthRequirement;                     // minimum amount of eth required to buy credibytes

  address itoContract = address(this);          // the address that holds the credits total supply
  uint256 public remaining_itoCreditsSupply;             // the remaining credibytes that are available for purchase

  uint256 public itoTotalParticipants;                  // the amount of ito user participants 
    
    
  event CredibytesPurchase(                             // Event for credibytes purchase logging
    address indexed purchaser,                          // who paid for the credits
    address indexed beneficiary,                        // who received the credits
    uint256 ethAmount,                                  // ethers paid for credits
    uint256 credibyteAmount                             // amount of credits purchased
  );
  event CredibytesRedemption(                           // Event for credibytes redemption
    address indexed redeemer,                           // user redeeming
    uint256 indexed creditsAmount,                      // amount of credits getting redeemed from credibytes
    uint256 time                                        // time of redemption
  );    
  event developerEthWithdrawal(                         // event for developer withdrawing eth
    address indexed to,                                 // address the developer is sending the eth to
    uint256 indexed amount,                             // the amount of eth being sent
    uint256 indexed timeOfWithdrawal                    // the block timestamp of the withdrawal
  );
  event ethDepositToDeveloper(                          // event for developer receiving eth
    address indexed from,                               // address that sent the eth
    uint256 indexed amount,                             // the amount of eth being sent
    uint256 indexed timeOfDeposit                       // the block timestamp of the deposit
  );
  event developerCreditsWithdrawal(                     // event for developer withdrawing credits (helps users prepare for a dump if need be)
    address indexed to,                                 // the address receiving the credits
    uint256 indexed amount,                             // the amount of credits being withdrawn
    uint256 indexed timeOfWithdrawal                    // the block timestamp of the withdrawal
  );

  constructor() {
    deploymentDate = block.timestamp;
    timelockActivationDate = deploymentDate + 4 weeks;
    hasFinalised = false;
    conversionRate_EthToCredits = 10000;
    minEthRequirement = 1 ether;                                                // the minimum amount required to purchase credibytes
    
    users[itoContract].hasContractAccess = true;                                // is given contract access for contractApprove()
    remaining_itoCreditsSupply = 85000000;                                       // 8,500,000 credits available
  }


//  ----------------------------------------------------
//                      Dashboard 
//  ----------------------------------------------------

  /// @notice Allows owner to update the eth to credibytes conversion rate.
  /// @param _newRate new eth to credibytes conversion rate.
  function setRate_EthToCredits(uint _newRate) public onlyOwner {
    conversionRate_EthToCredits = _newRate;
  }

  /// @notice Allows owner to update the minimum amount of eth to partake in the ITO.
  /// @param _newMinimumRequirement the new minimum amount of eth to partake in the ITO.
  function updateMinimumRequirement(uint _newMinimumRequirement) public onlyOwner {
      minEthRequirement = _newMinimumRequirement;
  }

  function finalise() public onlyOwner {    // Allows owner to finish the ITO before the timelock.
    hasFinalised = true;
  }



//  ----------------------------------------------------
//                      ITO Timelock 
//  ----------------------------------------------------

  uint256 public deploymentDate;              // The block when the timer begins counting from.
  uint256 public timelockActivationDate;      // The block when the contract locks/stops functioning.

  bool public hasFinalised;

  // If: now <= timelockActivationDate, continue functionality of ITO.
  modifier ito_Timelock {
    require(
        block.timestamp <= timelockActivationDate || hasFinalised != true, 
        "ERROR: ITO phase is over: contract locked & no longer functional."
      );
    _;
  }
  
  // Allows the 
  modifier canRedeem {
    require(
        block.timestamp >= timelockActivationDate || hasFinalised == true, 
        "ERROR: ITO phase is currently underway: can redeem once finalised or timelock has activated."
      );
    _;
  }


//  ----------------------------------------------------
//         Developer Funds Functions + Timelock
//  ----------------------------------------------------

  // Prevents developer(s) from withdrawing credits instantly after the ito has finished
  modifier creditsTimeLock {
    require(
      timelockActivationDate >= timelockActivationDate + 26 weeks, 
      "ERROR: Wait until timelock period is over to access functionality."
      );
    _;
  }

  // Allows users to view when the dev. timelock is over
  function viewTimeLockStatus() external view returns (
      uint256 timelockCommenced, 
      uint256 timelockCompletition, 
      uint256 timeRemaining
    ) { 
    return (
      timelockActivationDate,
      timelockActivationDate + 26 weeks,
      (timelockActivationDate + 26 weeks).sub(block.timestamp)
    );
  }

  // Allows the developer to withdraw "x" amount of  the remaining, unsold credits, or send them to the credits contract
  function developerCreditsWithdraw(address _to, uint256 _amount) permissionRequired creditsTimeLock external {
      users[itoContract].creditBalance = users[itoContract].creditBalance.sub(_amount);
      users[_to].creditBalance = users[_to].creditBalance.add(_amount);
      emit developerEthWithdrawal(_to, _amount, block.timestamp);
  } 

  // Allows the developer to withdraw a desired amount of ETH to their desired address
  function developerEthWithdraw(address _to, uint256 _amount) permissionRequired external {
      _to.transfer(_amount);
      emit developerEthWithdrawal(_to, _amount, block.timestamp);
  } 


//  ----------------------------------------------------
//                 External Functions 
//  ----------------------------------------------------

  // Allows the user to conver their credits to credits.
  function redeemCredits() canRedeem public returns (uint256 convertedAmount, bool sucess){
    require(users[msg.sender].credibyteBalance != 0, "ERROR: No credits remaining.");
    uint256 _conversionAmount = validateConversion();                                           // checks how many credits user will receive
    commenceConversion(_conversionAmount);                                                      // transfers credits to user
    emit CredibytesRedemption(msg.sender, _conversionAmount, block.timestamp);
    return (_conversionAmount, true);
  }

  // Transfers eth to designated collector & transfers credits to beneficiary. 
  function buyCredibytes_withETH(address _beneficiary) ito_Timelock public payable {
    uint256 ethAmount = msg.value;                                                              // ethAmount becomes msg.value
    
    _preValidatePurchase(_beneficiary, ethAmount);                                              // validates tx isn't sending 0 wei
    uint256 credibyteAmount = _getCredibyteAmount(ethAmount);                                   // calculates the amount of credits to be created
    
    _forwardFunds(ethAmount);                                                                   // transfers eth to itoCollector
    totalEthRaised = totalEthRaised.add(ethAmount);                                             // updates state: totalEthRaised

    _processPurchase(_beneficiary, credibyteAmount);                                            // transfers credits to beneficiary                       
    emit CredibytesPurchase(msg.sender, _beneficiary, ethAmount, credibyteAmount); 
  }

  // Views the inputted user's credibyte balance
  function viewCredibyeBalance(address user) external view returns (uint256 _credibyteBalance) {
    return users[user].credibyteBalance;
  }

  // Views how many remaining credibytes there are for purchase, with the total eth value of the remaining
  function viewRemainingCredibytesForPurchase() external view returns (
    uint256 remainingCredibytesForPurchase, 
    uint256 ethValueOfRemainingCredibytesForPurchase
    ) {
    return(
      remaining_credibyteSupply,
      remaining_credibyteSupply.div(10000)
    );
  }

  // If unlocked, call buyCredits_forEth || If locked, revert tx.
  receive() override external payable {
    if(block.timestamp <= timelockActivationDate) {
      buyCredibytes_withETH(msg.sender); 
    } else { revert(); }
  }


//  ----------------------------------------------------
//         Redeem Credits Internal Functions 
//  ----------------------------------------------------

  function validateConversion() internal 
    returns(
      uint256 currentCredibyteConversion 
    ) {
    require (
      users[msg.sender].remainingTimeUntilNextConversion <= block.timestamp || users[msg.sender].redemptionCounter == 0,
      "ERROR: Must wait the remaining time until next redeption."
    );
    require (
      users[msg.sender].credibyteBalance != 0,
      "ERROR: Insufficient credibyte balance to redeem."
    );
        if(users[msg.sender].redemptionCounter == 0) {
          users[msg.sender].redemptionCounter = users[msg.sender].redemptionCounter.add(1);       // adds 1 onto the user's current redemption counter
          users[msg.sender].remainingTimeUntilNextConversion = block.timestamp + 4 weeks;         // adds 1 month until user's next redemption activation
          return users[msg.sender].credibyteBalance.div(4);                                       // i.e. balance = 1000, calculates 250
        } 
          else if (users[msg.sender].redemptionCounter == 1) {
            users[msg.sender].redemptionCounter = users[msg.sender].redemptionCounter.add(1);     // adds 1 onto the user's current redemption counter
            users[msg.sender].remainingTimeUntilNextConversion = block.timestamp + 4 weeks;       // adds 1 month until user's next redemption activation
            return users[msg.sender].credibyteBalance.div(3);                                     // i.e. balance = 750, calculates 250 
        } 
          else if (users[msg.sender].redemptionCounter == 2) {
            users[msg.sender].redemptionCounter = users[msg.sender].redemptionCounter.add(1);     // adds 1 onto the user's current redemption counter
            users[msg.sender].remainingTimeUntilNextConversion = block.timestamp + 4 weeks;       // adds 1 month until user's next redemption activation
            return users[msg.sender].credibyteBalance.div(2);                                     // i.e. balance = 500, calculates 250  
        } 
          else if (users[msg.sender].redemptionCounter == 3) {
            users[msg.sender].redemptionCounter = users[msg.sender].redemptionCounter.add(1);     // adds 1 onto the user's current redemption counter
            users[msg.sender].remainingTimeUntilNextConversion = 0;     
            users[msg.sender].fullyConverted = true;
            return users[msg.sender].credibyteBalance;                                            // i.e. balance = 250, calculates remaining       
        }
    }

  function commenceConversion(uint256 _conversionAmount) internal {
    users[msg.sender].credibyteBalance = 0;                                                                  // sets user's credibyte balance to 0
    credits.contractApprove(creditsContract, msg.sender, _conversionAmount);
    credits.transferFrom(creditsContract, msg.sender, _conversionAmount);                                    // transfers credits from to caller
    // users[creditsContract].creditBalance = users[creditsContract].creditBalance.sub(_conversionAmount);   // deducts credits from owner wallet
    // remainingUnheldCredits = users[creditsContract].creditBalance;                                        // updates remaining unheld credits
    // users[msg.sender].creditBalance = users[msg.sender].creditBalance.add(_conversionAmount);             // gives user converted credits amount
    // totalCreditsHeld = totalCreditsSupply.sub(remainingUnheldCredits);                                    // updates total credits held
  }


//  ----------------------------------------------------
//         buyCredits_forETH Internal Functions 
//  ----------------------------------------------------

  function _preValidatePurchase(address _beneficiary, uint256 _ethAmount) ito_Timelock view internal {
    require(
        remaining_credibyteSupply >= (_ethAmount.mul(conversionRate_EthToCredibytes)).div(1000000000000000000), // (1 eth * 10,000)/ 1 eth = 10,000 credibytes
        "ERROR: Insufficent remaining credibyte supply to purchase, check remaining supply and adjust purchase amount."
      );
    require(
        _beneficiary != itoContract && _beneficiary != creditsContract,
        "ERROR: Unable to purchase credibytes for itoContract or creditsContract."
      );
    require(
        _ethAmount >= minEthRequirement, 
        "ERROR: Does not meet the minimum purchasing requirement: refer to minEthRequirement."
      );
  }

  function _getCredibyteAmount(uint256 _ethAmount) ito_Timelock internal view returns (uint256) {
    return (_ethAmount.mul(conversionRate_EthToCredits)).div(1000000000000000000);   // (1 eth * 10,000)/ 1 eth = 10,000 credibytes
  }

  // Transfers eth (msg.value) to developerContract
  function _forwardFunds(uint256 ethAmount) ito_Timelock internal {
    itoContract.transfer(ethAmount);
    emit ethDepositToDeveloper(msg.sender, msg.value, block.timestamp);
  }

  // Calls _deliverTokens.
  function _processPurchase(address _beneficiary, uint256 _credibyteAmount) ito_Timelock internal {
    _deliverCredibytes(_beneficiary, _credibyteAmount);

  }

  // Updates credibyte balance
  function _deliverCreditsRBond(address _beneficiary, uint256 _credibyteAmount) ito_Timelock internal {
    remaining_itoCreditsSupply = remaining_itoCreditsSupply.sub(_credibyteAmount);
    users[_beneficiary].credibyteBalance = users[_beneficiary].credibyteBalance.add(_credibyteAmount);
    if(users[_beneficiary].redemptionCounter != 0 || users[_beneficiary].fullyConverted != false) {
      users[_beneficiary].redemptionCounter = 0;
      users[_beneficiary].fullyConverted = false;
    }
    if(users[_beneficiary].hasParticipatedInITO != true) {                                    // adds users to hasParticipated if they haven't
      users[_beneficiary].hasParticipatedInITO = true;
      itoTotalParticipants = itoTotalParticipants.add(1);
    }
  }
}
3
  • Post the full contact code. Jan 10 at 10:06
  • What solc version are you using? Jan 10 at 10:09
  • The code doesn't compile it is missing Credits contract. Also why does it inherit from Credits and also contains a Credits instance itself? After removing everything not mentioned in the question the code compiles without any issue. Please include a minimal reproducible example it is just guessing otherwise.
    – Ismael
    Jan 10 at 23:21
0

I think my VS Code is messed up, because I tried using it in remix and it works fine. If anyone knows how to fix this VS Code problem LMK please!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.