function executeSubscription(
        address from, 
        address to, 
        address tokenAddress, 
        uint256 tokenAmount, 
        uint256 periodSeconds, 
        uint256 gasPrice, 
        bytes signature 
    )
        public
        returns (bool success)
    {
        
        
        bytes32 subscriptionHash = getSubscriptionHash(
            from, to, tokenAddress, tokenAmount, periodSeconds, gasPrice
        );
        address signer = getSubscriptionSigner(subscriptionHash, signature);

        
        require(signer == from, "Invalid Signature");
        
        require(
            block.timestamp >= nextValidTimestamp[subscriptionHash],
            "Subscription is not ready"
        );

        
        
        require( requiredToAddress == address(0) || to == requiredToAddress );
        require( requiredTokenAddress == address(0) || tokenAddress == requiredTokenAddress );
        require( requiredTokenAmount == 0 || tokenAmount == requiredTokenAmount );
        require( requiredPeriodSeconds == 0 || periodSeconds == requiredPeriodSeconds );
        require( requiredGasPrice == 0 || gasPrice == requiredGasPrice );

        
        nextValidTimestamp[subscriptionHash] = block.timestamp.add(periodSeconds);

        
        uint256 startingBalance = ERC20(tokenAddress).balanceOf(to);
        require(
          ERC20(tokenAddress).transferFrom(from,to,tokenAmount),
          "Transfer Failed"
        );
        require(
          (startingBalance+tokenAmount) == ERC20(tokenAddress).balanceOf(to),
          "Crappy ERC20 is a bad kitty."
        );

        emit ExecuteSubscription(
            from, to, tokenAddress, tokenAmount, periodSeconds, gasPrice
        );

        
        
        
        if (gasPrice > 0) {
            
            
            
            
            
            
            
            

            require(
                ERC20(tokenAddress).transferFrom(from, msg.sender, gasPrice),
                "Failed to pay gas as from account"
            );
        }

        return true;
    }