contract feesProtocolProcesses is feesProtocolStorage{
    function withdrawUnlockedToken(uint _amount, address _benficiary) public{
        require(_benficiary == msg.sender, "Sender Approval Error!"); 
        require(SafeMath.safeAdd(withdrewTokenBalance, _amount) <= unloackedTokenBalance, "Insufficient Total Unlocked Balance!");
        require(SafeMath.safeAdd(withdrawBalance[_benficiary], _amount) <= unlockedBalance[_benficiary], "Insufficient User Unlocked Balance!");
        
        if (!Token(projectToken).transfer(msg.sender, _amount)) { revert("withdraw failed!"); }
        
        emit Withdraw(projectToken, msg.sender, _amount, withdrawBalance[msg.sender]); // _benficiary
        withdrawBalance[_benficiary] = SafeMath.safeAdd(withdrawBalance[_benficiary], _amount);
        withdrewTokenBalance = SafeMath.safeAdd(withdrewTokenBalance, _amount);
    }
    
    function distributingPrepration(address[] memory _tokens, address[] memory _traders, 
        address[] memory _tradersToken, uint[] memory _tokensV, uint[] memory _tokensVeth, 
        uint[] memory _tradersV, uint[] memory _tradersVeth,
        address[] memory _tradersF, address[] memory _tradersTokenF,
        uint[] memory _tradersFees, uint[] memory _tradersFeth
    ) public onlyOwner{
        
        // _tokens _traders  _tradersToken  _tokensV  _tokensVeth  _tradersV  _tradersVeth
        require(usedVolume == 0, "distribution is already done!");
        require(_tokens.length == _tokensV.length, "inputs not matched 1!");
        require(_tokens.length == _tokensVeth.length, "inputs not matched 2!");
        require(_traders.length == _tradersV.length, "inputs not matched 3!");
        require(_traders.length == _tradersVeth.length, "inputs not matched 4!"); 
        require(_traders.length == _tradersToken.length, "inputs not matched 5!");
        require(_tradersF.length == _tradersTokenF.length, "inputs not matched 6!");
        require(_tradersF.length == _tradersFees.length, "inputs not matched 7!"); 
        require(_tradersF.length == _tradersFeth.length, "inputs not matched 8!");
        
        // first for tokens 
        for(uint i=0; i<_tokens.length; i++){
            platformVolumeUsed[_tokens[i]] = SafeMath.safeAdd(platformVolumeUsed[_tokens[i]], _tokensV[i]);
            platformVolumeUsedInETH[_tokens[i]] = SafeMath.safeAdd(platformVolumeUsedInETH[_tokens[i]], _tokensVeth[i]);
            if(_tokens[i] != address(0)){
                platformVolumeUsedInETH[address(0)] = SafeMath.safeAdd(platformVolumeUsedInETH[address(0)], _tokensVeth[i]);
            }
        }
        
        // Second for traders 
        for(uint i=0; i<_traders.length; i++){
            tradersVolumeUsed[_tradersToken[i]][_traders[i]] = SafeMath.safeAdd(tradersVolumeUsed[_tradersToken[i]][_traders[i]] , _tradersV[i]);
            tradersVolumeUsedInETH[_tradersToken[i]][_traders[i]] = SafeMath.safeAdd(tradersVolumeUsedInETH[_tradersToken[i]][_traders[i]], _tradersVeth[i]);
            if(_tradersToken[i] != address(0)){
                tradersVolumeUsedInETH[address(0)][_traders[i]] = SafeMath.safeAdd(tradersVolumeUsedInETH[address(0)][_traders[i]], _tradersVeth[i]);
            }
            
            // I think there is no need to save this data since it can be get off-chain 
            //traderTotalVolume[upcomingLevel][upcomingRound][_tradersToken[i]][_traders[i]] = SafeMath.safeAdd( traderTotalVolume[upcomingLevel][upcomingRound][_tradersToken[i]][_traders[i]] , _tradersV[i]);
            //traderTotalVolumeInEth[upcomingLevel][upcomingRound][_tradersToken[i]][_traders[i]] = SafeMath.safeAdd(traderTotalVolumeInEth[upcomingLevel][upcomingRound][_tradersToken[i]][_traders[i]], _tradersVeth[i]);
            
        }
        
        // third for fees 
        for(uint i=0; i<_tradersF.length; i++){
            // fees for Eth is saved inside tradersFeesDeserved for address(0)
            // fees for Tokens are save indside tradersFeesDeservedInEth all under one address(0) 
            platformFeesDeserved[_tradersTokenF[i]] = SafeMath.safeAdd(platformFeesDeserved[_tradersTokenF[i]], _tradersFees[i]);
            platformFeesDeservedInEth[_tradersTokenF[i]] = SafeMath.safeAdd(platformFeesDeservedInEth[_tradersTokenF[i]], _tradersFeth[i]);
            
            tradersFeesDeserved[_tradersTokenF[i]][_tradersF[i]] = SafeMath.safeAdd(tradersFeesDeserved[_tradersTokenF[i]][_tradersF[i]] , _tradersFees[i]);
            tradersFeesDeservedInEth[_tradersTokenF[i]][_tradersF[i]] = SafeMath.safeAdd(tradersFeesDeservedInEth[_tradersTokenF[i]][_tradersF[i]], _tradersFeth[i]);
            
            // safe fees valued in ETH for all traded token using one Token only for each user 
            if(_tradersTokenF[i] != address(0)){
                platformFeesDeservedInEth[address(0)] = SafeMath.safeAdd(platformFeesDeservedInEth[address(0)], _tradersFeth[i]);
                tradersFeesDeservedInEth[address(0)][_tradersF[i]] = SafeMath.safeAdd(tradersFeesDeservedInEth[address(0)][_tradersF[i]], _tradersFeth[i]);
            }
            
        }
        
        usedVolume = 1;  
        
    }
    
    // benficiaries (1) for distributing  || benficiaries2 for unlocking 
    function distributingAndUnlocking(address[] memory _tokens, address[] memory _benficiaries, 
        uint[] memory _groups, uint[] memory _amounts, 
        address[] memory _benficiaries2, uint[] memory _groups2, uint[] memory _amounts2, 
        uint _nextLevel, uint _nextRound
    ) public payable onlyOwner{ // payable
        
        require(usedVolume == 1, "do prepration first!");
        require(_tokens.length == _benficiaries.length, "inputs not matched 1!");
        require(_tokens.length == _groups.length, "inputs not matched 2!");
        require(_tokens.length == _amounts.length, "inputs not matched 3!");
        require(_benficiaries2.length == _groups2.length, "inputs not matched 4!");
        require(_benficiaries2.length == _amounts2.length, "inputs not matched 5!");
        
        // first we unlock Project token 
        for(uint i=0; i<_benficiaries2.length; i++){
            require(SafeMath.safeAdd(unloackedTokenBalance, _amounts2[i])  <= propertyAmount, "there isn't enough balance to unlock!");
            
            unloackedTokenBalance = SafeMath.safeAdd(unloackedTokenBalance, _amounts2[i]);
            unlockedBalance[_benficiaries2[i]] = SafeMath.safeAdd(unlockedBalance[_benficiaries2[i]], _amounts2[i]);
            unlockedRoundsBalance[upcomingLevel][upcomingRound][_groups2[i]][_benficiaries2[i]] = SafeMath.safeAdd(unlockedRoundsBalance[upcomingLevel][upcomingRound][_groups2[i]][_benficiaries2[i]], _amounts2[i]);
            
            if(_groups2[i] == 4){
                OwnershipTotalAllocated = SafeMath.safeAdd(OwnershipTotalAllocated, _amounts2[i]);
                tokenGroupsOwnershipAlloced[4] = SafeMath.safeAdd(tokenGroupsOwnershipAlloced[4], _amounts2[i]);
                tokenOwnersBalance[4][_benficiaries2[i]] = SafeMath.safeAdd(tokenOwnersBalance[4][_benficiaries2[i]], _amounts2[i]);
            }
        }
        
        // Second we distribute fees 
        DEXplatform(dex).distributeFeesPool(_tokens, _benficiaries, _amounts);
        
        // Third we update basic virables 
        upcomingLevel = _nextLevel;
        upcomingRound = _nextRound; 
        usedVolume = 0;
    }
    
}
function distributingAndUnlocking(address[] memory _tokens, address[] memory _benficiaries, 
    uint[] memory _groups, uint[] memory _amounts, 
    address[] memory _benficiaries2, uint[] memory _groups2, uint[] memory _amounts2, 
    uint _nextLevel, uint _nextRound
) public payable onlyOwner{ // payable
        
    require(usedVolume == 1, "do prepration first!");
    require(_tokens.length == _benficiaries.length, "inputs not matched 1!");
    require(_tokens.length == _groups.length, "inputs not matched 2!");
    require(_tokens.length == _amounts.length, "inputs not matched 3!");
    require(_benficiaries2.length == _groups2.length, "inputs not matched 4!");
    require(_benficiaries2.length == _amounts2.length, "inputs not matched 5!");
        
    // first we unlock Project token 
    for(uint i=0; i<_benficiaries2.length; i++){
        require(SafeMath.safeAdd(unloackedTokenBalance, _amounts2[i])  <= propertyAmount, "there isn't enough balance to unlock!");
            
        unloackedTokenBalance = SafeMath.safeAdd(unloackedTokenBalance, _amounts2[i]);
        unlockedBalance[_benficiaries2[i]] = SafeMath.safeAdd(unlockedBalance[_benficiaries2[i]], _amounts2[i]);
        unlockedRoundsBalance[upcomingLevel][upcomingRound][_groups2[i]][_benficiaries2[i]] = SafeMath.safeAdd(unlockedRoundsBalance[upcomingLevel][upcomingRound][_groups2[i]][_benficiaries2[i]], _amounts2[i]);
            
        if(_groups2[i] == 4){
            OwnershipTotalAllocated = SafeMath.safeAdd(OwnershipTotalAllocated, _amounts2[i]);
            tokenGroupsOwnershipAlloced[4] = SafeMath.safeAdd(tokenGroupsOwnershipAlloced[4], _amounts2[i]);
            tokenOwnersBalance[4][_benficiaries2[i]] = SafeMath.safeAdd(tokenOwnersBalance[4][_benficiaries2[i]], _amounts2[i]);
        }
    }
        
    // Second we distribute fees 
    DEXplatform(dex).distributeFeesPool(_tokens, _benficiaries, _amounts);
        
    // Third we update basic virables 
    upcomingLevel = _nextLevel;
    upcomingRound = _nextRound; 
    usedVolume = 0;
}

// benficiaries (1) for distributing  || benficiaries2 for unlocking 