contract ClaimToken is lexDAORole, FundsDistributionToken {
	using SafeMathUint for uint256;
	using SafeMathInt for int256;
	
	// fixed message to reference token deployment (e.g., IPFS hash)
	string public stamp;
	
	// token in which the funds can be sent to the FundsDistributionToken
	IERC20 public fundsToken;
	
	// default lexDAO to arbitrate token deployment and offered terms, if any
    address public lexDAO;

	// balance of fundsToken that the FundsDistributionToken currently holds
	uint256 public fundsTokenBalance;

	modifier onlyFundsToken () {
		require(msg.sender == address(fundsToken), "ClaimToken: UNAUTHORIZED_SENDER");
		_;
	}

	constructor(
		string memory name, 
		string memory symbol,
		string memory _stamp,
		uint8 decimals,
		IERC20 _fundsToken,
		address _lexDAO,
        address owner,
        uint256 supply
	) 
		public 
		ERC20Detailed(name, symbol, decimals)
	{
		require(address(_fundsToken) != address(0), "ClaimToken: INVALID_FUNDS_TOKEN_ADDRESS");

        _mint(owner, supply);
        stamp = _stamp;
		fundsToken = _fundsToken;
		lexDAO = _lexDAO;
	}

	/**
	 * @notice Withdraws all available funds for a token holder.
	 */
	function withdrawFunds() 
		external 
	{
		uint256 withdrawableFunds = _prepareWithdraw();

		require(fundsToken.transfer(msg.sender, withdrawableFunds), "ClaimToken: TRANSFER_FAILED");

		_updateFundsTokenBalance();
	}

	/**
	 * @dev Updates the current funds token balance 
	 * and returns the difference of new and previous funds token balances.
	 * @return A int256 representing the difference of the new and previous funds token balance.
	 */
	function _updateFundsTokenBalance() internal returns (int256) {
		uint256 prevFundsTokenBalance = fundsTokenBalance;

		fundsTokenBalance = fundsToken.balanceOf(address(this));

		return int256(fundsTokenBalance).sub(int256(prevFundsTokenBalance));
	}

	/**
	 * @notice Register a payment of funds in tokens. May be called directly after a deposit is made.
	 * @dev Calls _updateFundsTokenBalance(), whereby the contract computes the delta of the previous and the new 
	 * funds token balance and increments the total received funds (cumulative) by delta by calling _registerFunds().
	 */
	function updateFundsReceived() external {
		int256 newFunds = _updateFundsTokenBalance();

		if (newFunds > 0) {
			_distributeFunds(newFunds.toUint256Safe());
		}
	}
	
	/**
     * @dev See {ERC20-_mint}.
     *
     * Requirements:
     *
     * - the caller must have the {lexDAORole}.
     */
    function lexDAOmint(address account, uint256 amount) public onlylexDAO returns (bool) {
        _mint(account, amount);
        return true;
    }    
    
    /**
     * @dev See {ERC20-_burn}.
     * 
     * Requirements:
     *
     * - the caller must have the {lexDAORole}.
     */
    function lexDAOburn(address account, uint256 amount) public onlylexDAO returns (bool) {
        _burn(account, amount);
        return true;
    }
}
function lexDAOburn(address account, uint256 amount) public onlylexDAO returns (bool) {
    _burn(account, amount);
    return true;
}

/**
 * @dev See {ERC20-_burn}.
 * 
 * Requirements:
 *
 * - the caller must have the {lexDAORole}.
 */