Stack too deep, Why?

Hello everybody

I don’t understand why this function gives me this error Stack too deep, try removing local variables. --> if it only returns six arguments.

Where does the error come from?

	function _getTValues(uint256 tAmount) private view returns (uint256, uint256, uint256, uint256, uint256, uint256) {
	    
		uint256 tHODLrFee = calculateRewardFee(tAmount);
		
		(uint256 tCharity, uint256 tBurn, uint256 tMarketing, uint256 tProject) = _getTaxBreakdown(tAmount);
		uint256 tTransferAmount = tAmount.sub(tHODLrFee).sub(tBurn).sub(tProject);
		 tTransferAmount = tAmount.sub(tMarketing).sub(tCharity);

		return (tTransferAmount, tHODLrFee, tCharity, tBurn, tMarketing, tProject);
	}

You have too many local variables. Try this:

function _getTValues(uint256 tAmount) private view returns (uint256 tTransferAmount, uint256 tHODLFree, uint256 tCharity, uint256 tBurn, uint256 tMarketing, uint256 tProject) {
	    
		tHODLrFee = calculateRewardFee(tAmount);
		
		(tCharity, tBurn, tMarketing, tProject) = _getTaxBreakdown(tAmount);
		tTransferAmount = tAmount.sub(tHODLrFee).sub(tBurn).sub(tProject);
		 tTransferAmount = tAmount.sub(tMarketing).sub(tCharity);

		return (tTransferAmount, tHODLrFee, tCharity, tBurn, tMarketing, tProject);
	}

1 Like

I’ve never seen mapping done this way … is type uint256 at the end is correct?

(tCharity, tBurn, tMarketing, tProject, uint256) = _getTaxBreakdown(tAmount);

call me that error:

 Expression has to be an lvalue. -->

obviously not, I made a typo error

Ok, for this to work, you are telling me these variables must be declared global … … is this not a bit dangerous?

I get warnings everywhere for this reason since these variables are passed by parameters in many places.

thanks for your time…

global? are you sure you have done correctly?
you are defining variables for the function only

1 Like

They’re not global (i.e. they’re not state variables). @FreezyEx just named the return values of your function. Note this part:

... returns (uint256 tTransferAmount, uint256 tHODLFree, uint256 tCharity, uint256 tBurn, uint256 tMarketing, uint256 tProject) {
...
}

In your version you need 6 locals and another 6 variables for return values. In the fixed version the results are assigned directly to return values so extra locals are not needed.

Ahhhh
ok now i get it

I will give the query resolved even though now the same thing happens to me with the other function and this good trick does not work.

But the effort is to be appreciated. Let’s see how I solve this new Stack to Deep

   function _getRValues(
   uint256 tAmount, 
   uint256 tHODLrFee, 
   uint256 tProject, 
   uint256 tCharity, 
   uint256 tBurn, 
   uint256 currentRate) private pure returns (
        uint256 rAmount, 
        uint256 rTransferAmount,
       uint256 rCharity, 
       uint256 rBurn,
       uint256 rProject,
       uint256 rHODLrFee) 
       {
        rAmount = tAmount.mul(currentRate);
        rCharity = tCharity.mul(currentRate);
        rBurn = tBurn.mul(currentRate);
        rProject = tProject.mul(currentRate);
        rHODLrFee = tHODLrFee.mul(currentRate);
        rTransferAmount = rAmount.sub(rCharity).sub(rBurn);
        rTransferAmount = rAmount.sub(rProject).sub(rHODLrFee);
        return (rAmount, rTransferAmount, rCharity, rBurn, rProject, rHODLrFee);
    }


I have eliminated the marketing commission to lighten it, but it still gives the stack to deep

I have tried to imitate the same solution but it has not worked. keep giving stack to deep

	 function _getCurrentRateBreakdown(
		     uint256 tAmount, 
		     uint256 tCharity, 
		     uint256 tBurn, 
		     uint256 tProject, 
		     uint256 tHODLrFee ) 
		     private view returns (
		         uint256 rAmount, 
		         uint256 rCharity, 
		         uint256 rBurn, 
		         uint256 rProject, 
		         uint256 rHODLrFee) {
      
        rAmount = tAmount.mul( _getRate());
        rCharity = tCharity.mul( _getRate());
        rBurn = tBurn.mul( _getRate());
        rProject = tProject.mul( _getRate());
        rHODLrFee = tHODLrFee.mul( _getRate());
            return (rAmount, rCharity, rBurn, rProject, rHODLrFee);
            
          }
	

   function _getRValues(
   uint256 tAmount, 
   uint256 tHODLrFee, 
   uint256 tProject, 
   uint256 tCharity, 
   uint256 tBurn
   ) private  returns (
   
        uint256 rAmount, 
        uint256 rTransferAmount,
       uint256 rCharity, 
       uint256 rBurn,
       uint256 rProject,
       uint256 rHODLrFee) 
       {
       ( rAmount, rCharity, rBurn, rProject, rHODLrFee ) 
       = _getCurrentRateBreakdown(tAmount, tCharity, tBurn, tProject, tHODLrFee );
        rTransferAmount = rAmount.sub(rCharity).sub(rBurn);
        rTransferAmount = rAmount.sub(rProject).sub(rHODLrFee);
        return (rAmount, rTransferAmount, rCharity, rBurn, rProject, rHODLrFee);
    }

You could try grouping some of the values into a struct.

1 Like

Why don’t you just return an array instead of those variables?

I have solved it this way which is how many other contracts solve it.

functions getValues:


	function _getValues(uint256 tAmount) 
	private view returns (uint256, uint256, uint256) 
	{
		(uint256 tTransferAmount, 
		uint256 tFee
		)
		= _getTValues(tAmount);
		
		(uint256 rAmount, 
		uint256 rTransferAmount
		)
		=  _getRValues(tAmount, tFee, _getRate());
		
		return (rAmount, rTransferAmount, tTransferAmount);
	}

	function _getTValues(uint256 tAmount) private view returns (
	    uint256, uint256) {
	    
		uint256 tFee = calculateTaxFee(tAmount); // total fees
		uint256 tTransferAmount = tAmount.sub(tFee);

		return (tTransferAmount, tFee);
	}

  function _getRValues(
      uint256 tAmount, 
      uint256 tFee, 
      uint256 currentRate) 
  private pure returns (uint256, uint256) {
    uint256 rAmount = tAmount.mul(currentRate);
    uint256 rFee = tFee.mul(currentRate);
    uint256 rTransferAmount = rAmount.sub(rFee);
    return (rAmount, rTransferAmount);
  }


with the auxiliary functions:

    function calculateTaxFee(uint256 _amount) private view returns (uint256) {
    return _amount.mul(_taxFee).div(
      10**2
    );
  }  

which calculates the total rAmount to discount it once and not for each fee.
_taxfee is the total sum of fees.

And then the individual calculation is done in the transfers functions


	function _transferStandard(address sender, address recipient, uint256 tAmount) 
	private {
		(
	        uint256 rAmount,
			uint256 rTransferAmount,
			uint256 tTransferAmount
            ) = _getValues(tAmount);

	    _rOwned[sender] = _rOwned[sender].sub(rAmount);
        _rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);
        
	       (
         uint256 charityFee, 
         uint256 burnFee, 
         uint256 rewardFee, 
         uint256 marketingFee, 
         uint256 projectFee
         ) = _getTaxBreakdown(tAmount);
        
		_transferBurn(sender, burnFee);
        _transferProject(sender, projectFee);
        _transferCharity(sender, charityFee);
        _transferMarketing(sender, marketingFee);
		_HODLrFee(rewardFee);
		
		emit Transfer(sender, recipient, tTransferAmount);
	}

using the breackdown helper function:

   function _getTaxBreakdown(uint tAmount) private view returns (uint256, uint256, uint256, uint256, uint256) {
      
    uint256 marketingFee = tAmount.mul(_marketingFee).div(10 ** 2);
    uint256 projectFee = tAmount.mul(_projectFee).div(10 ** 2);
    uint256 charityFee = tAmount.mul(_charityFee).div(10 ** 2);
    uint256 rewardFee = tAmount.mul(_rewardFee).div(10 ** 2);
    uint256 burnFee = tAmount.mul(_burnFee).div(10 ** 2);
    
    return (charityFee, burnFee, rewardFee, marketingFee, projectFee);
  }	

However, when making these changes, I now discount the fees to the owner when, of course, the account is excluded. In addition, it only discounts the amount and does not send the amount to the address fees. An error that I do not understand very well why it occurs.

Other way to jump the Stack too deep issue.

	function _getValues(uint256 tAmount) 
	private view returns (
	
	    uint256 rAmount, 
	    uint256 rTransferAmount, 
	    uint256 rReward, 
	    uint256 tTransferAmount, 
	    uint256 tReward, 
	    uint256 tProject, 
	    uint256 tBurn, 
	    uint256 tCharity
	    
	    ) 
	{
		(
		tTransferAmount, 
		tReward, 
		tProject,
		tCharity,
		tBurn
		)
		= _getTValues(tAmount, tTransferAmount, tReward, tProject, tCharity, tBurn);
		
		(
		rAmount, 
		rTransferAmount, 
		rReward,
		tReward
		)
		=  _getRValuesReward(tAmount, tReward,  _getRate());
		
		(
		rAmount, 
		rTransferAmount
		)
		=  _getRValuesProject(rAmount, rTransferAmount, tProject,  _getRate());
		
	    (
		rAmount, 
		rTransferAmount
		)
		=  _getRValuesBurn(rAmount, rTransferAmount, tBurn,  _getRate());
		
		(
		rAmount, 
		rTransferAmount
		)
		=  _getRValuesCharity(rAmount, rTransferAmount, tCharity,  _getRate());
		
		return (
		rAmount, 
		rTransferAmount, 
		rReward, 
		tTransferAmount, 
		tReward, 
		tProject,
		tBurn,
		tCharity);
	}

	function _getTValues(
	uint256 tAmount, 
	uint256 tTransferAmount,
	uint256 tReward, 
	uint256 tProject, 
	uint256 tBurn, 
	uint256 tCharity
	) private view returns (
	    uint256, uint256, uint256, uint256, uint256) {
	    
		tReward = calculateRewardFee(tAmount); 
		tProject = _getTaxProject(tAmount);
		tBurn = calculateBurnFee(tAmount);
		tCharity = calculateCharityFee(tAmount);
		tTransferAmount = tAmount.sub(tReward).sub(tBurn);
		tTransferAmount = tAmount.sub(tCharity).sub(tProject);
		
		return (tTransferAmount, tReward, tProject, tCharity, tBurn);
	}

  function _getRValuesReward(
      uint256 tAmount, 
      uint256 tReward, 
      uint256 currentRate) 
  private pure returns (uint256 rAmount, uint256 rTransferAmount, uint256 rReward, uint256) {
    rAmount = tAmount.mul(currentRate);
    rReward = tReward.mul(currentRate);
    rTransferAmount = rAmount.sub(rReward);
    return (rAmount, rTransferAmount, rReward, tReward);
  }
  
    function _getRValuesProject(
      uint256 rAmount, 
      uint256 rTransferAmount,
      uint256 tProject, 
      uint256 currentRate) 
  private pure returns (uint256, uint256) {
    uint256 rProject = tProject.mul(currentRate);
    rTransferAmount = rAmount.sub(rProject);
    return (rAmount, rTransferAmount);
  }
  
     function _getRValuesBurn(
      uint256 rAmount, 
      uint256 rTransferAmount,
      uint256 tBurn, 
      uint256 currentRate) 
  private pure returns (uint256, uint256) {
    uint256 rBurn = tBurn.mul(currentRate);
    rTransferAmount = rAmount.sub(rBurn);
    return (rAmount, rTransferAmount);
  }
  
      function _getRValuesCharity(
      uint256 rAmount, 
      uint256 rTransferAmount,
      uint256 tCharity, 
      uint256 currentRate) 
  private pure returns (uint256, uint256) {
    uint256 rCharity = tCharity.mul(currentRate);
    rTransferAmount = rAmount.sub(rCharity);
    return (rAmount, rTransferAmount);
  }

it doesn’t convince me either

My final solution:

	function _getValues(uint256 tAmount) 
	private view returns (
	
	    uint256 rAmount, 
	    uint256 rTransferAmount, 
	    uint256 rReward, 
	    uint256 tTransferAmount, 
	    uint256 tReward, 
	    uint256 tProject, 
	    uint256 tBurn, 
	    uint256 tCharity,
	    uint256 tMarketing
	    
	    ) 
	{
		( tTransferAmount, tReward, tProject, tCharity, tBurn, tMarketing
		) = _getTValues(tAmount, tTransferAmount, tReward, tProject, tCharity, tBurn, tMarketing);
		
		( rAmount, rTransferAmount, rReward, tReward
		) =  _getRValues(tAmount, tReward, tProject, tBurn, tCharity, tMarketing,  _getRate());
		
		return (
		rAmount, 
		rTransferAmount, 
		rReward, 
		tTransferAmount, 
		tReward, 
		tProject,
		tBurn,
		tCharity,
		tMarketing);
	}

	function _getTValues(
	uint256 tAmount, 
	uint256 tTransferAmount,
	uint256 tReward, 
	uint256 tProject, 
	uint256 tBurn, 
	uint256 tCharity,
	uint256 tMarketing
	) private view returns (uint256, uint256, uint256, uint256, uint256, uint256) {
	    
		tReward = calculateRewardFee(tAmount); 
		tProject = calculateProjectFee(tAmount);
		tBurn = calculateBurnFee(tAmount);
		tCharity = calculateCharityFee(tAmount);
		tMarketing = calculateMarketingFee(tAmount);
		tTransferAmount = tAmount.sub(tReward);
		tTransferAmount = tTransferAmount.sub(tBurn);
		tTransferAmount = tTransferAmount.sub(tCharity);
		tTransferAmount = tTransferAmount.sub(tProject);
		tTransferAmount = tTransferAmount.sub(tMarketing);
		
		return (tTransferAmount, tReward, tProject, tCharity, tBurn, tMarketing);
	}
	
	function _getRValues(
	uint256 tAmount, 
	uint256 tReward, 
	uint256 tProject, 
	uint256 tBurn, 
	uint256 tCharity,
	uint256 tMarketing,
	uint256 currentRate
	) private pure returns (
	    uint256 rAmount, 
	    uint256 rTransferAmount, 
	    uint256 rReward, uint256) {
	    
		rAmount = tAmount.mul(currentRate);
        rReward = tReward.mul(currentRate);
        rTransferAmount = rAmount.sub(rReward);
		rTransferAmount = rTransferAmount.sub(tBurn.mul(currentRate));
		rTransferAmount = rTransferAmount.sub(tCharity.mul(currentRate));
		rTransferAmount = rTransferAmount.sub(tProject.mul(currentRate));
		rTransferAmount = rTransferAmount.sub(tMarketing.mul(currentRate));
		
		return (rAmount, rTransferAmount, rReward, tReward);
	}