contract Unbonded is OwnableUpgradeSafe {
            
    using SafeMath for uint256;

    uint public TGE;
    uint public constant month = 30 days;
    uint constant decimals = 18;
    uint constant decMul = uint(10) ** decimals;
    
    address public communityAddress;

    uint public constant PRIVATE_POOL = 10000000 * decMul;
    uint public constant COMMUNITY_POOL = 12000000 * decMul;
    
    uint public currentPrivatePool = PRIVATE_POOL;
    uint public currentCommunityPool = COMMUNITY_POOL;
    
    IERC20 public token;
    
    mapping(address => uint) public privateWhitelist;

    constructor(address _communityAddress) public {
        __Ownable_init_unchained();

        communityAddress = _communityAddress;
    }

    /**
     * @dev Sets the Plutus ERC-20 token contract address
     */
    function setTokenContract(address _tokenAddress) public onlyOwner {
        token = IERC20(_tokenAddress);
    }

    /**
     * @dev Sets the current TGE from where the vesting period will be counted. Can be used only if TGE is zero.
     */
    function setTGE() public onlyOwner {
        require(TGE == 0, "TGE has already been set");
        TGE = now;
    }
    
    /**
     * @dev Sets each address from `addresses` as the key and each balance
     * from `balances` to the privateWhitelist. Can be used only by an owner.
     */
    function addToWhitelist(address[] memory addresses, uint[] memory balances) public onlyOwner {
        require(addresses.length == balances.length, "Invalid request length");
        
        for(uint i = 0; i < addresses.length; i++) {
            privateWhitelist[addresses[i]] = balances[i];
        }
    }
    
    /**
     * @dev claim private tokens from the contract balance.
     * `amount` means how many tokens must be claimed.
     * Can be used only by an owner or by any whitelisted person
     */
    function claimPrivateTokens(uint amount) public {
        require(privateWhitelist[msg.sender] > 0, "Sender is not whitelisted");
        require(privateWhitelist[msg.sender] >= amount, "Exceeded token amount");
        require(currentPrivatePool >= amount, "Exceeded private pool");
        
        currentPrivatePool = currentPrivatePool.sub(amount);
        
        privateWhitelist[msg.sender] = privateWhitelist[msg.sender].sub(amount);
        token.transfer(msg.sender, amount);
    }
    
    /**
     * @dev claim community tokens from the contract balance.
     * Can be used only by an owner or from communityAddress
     */
    function claimCommunityTokens() public {
        require(msg.sender == communityAddress || msg.sender == owner(), "Unauthorised sender");
        require(TGE > 0, "TGE must be set");
        
        // No vesting period
        uint amount = 0;
        if (now >= TGE  && currentCommunityPool == COMMUNITY_POOL) {
                currentCommunityPool -= 4800000*decMul;
                amount += 4800000*decMul;
        }

        if (now >= TGE + 1*month && currentCommunityPool == COMMUNITY_POOL - 4800000*decMul) {
                currentCommunityPool -= 1200000*decMul;
                amount += 1200000*decMul;
        }

        if (now >= TGE + 2*month && currentCommunityPool == COMMUNITY_POOL - 6000000*decMul) {
                currentCommunityPool -= 1200000*decMul;
                amount += 1200000*decMul;
        }

        if (now >= TGE + 3*month && currentCommunityPool == COMMUNITY_POOL - 7200000*decMul) {
                currentCommunityPool -= 1200000*decMul;
                amount += 1200000*decMul;
        }
        if (now >= TGE + 4*month && currentCommunityPool == COMMUNITY_POOL - 8400000*decMul) {
                currentCommunityPool -= 1200000*decMul;
                amount += 1200000*decMul;
        }
        if (now >= TGE + 5*month && currentCommunityPool == COMMUNITY_POOL - 9600000*decMul) {
                currentCommunityPool -= 1200000*decMul;
                amount += 1200000*decMul;
        }
        if (now >= TGE + 6*month && currentCommunityPool == COMMUNITY_POOL - 10800000*decMul) {
                currentCommunityPool -= 1200000*decMul;
                amount += 1200000*decMul;
        }
        
        // 25% each 6 months
        require(amount > 0, "nothing to claim");

        token.transfer(communityAddress, amount);
    }
}
function claimCommunityTokens() public {
    require(msg.sender == communityAddress || msg.sender == owner(), "Unauthorised sender");
    require(TGE > 0, "TGE must be set");
        
    // No vesting period
    uint amount = 0;
    if (now >= TGE  && currentCommunityPool == COMMUNITY_POOL) {
            currentCommunityPool -= 4800000*decMul;
            amount += 4800000*decMul;
    }

    if (now >= TGE + 1*month && currentCommunityPool == COMMUNITY_POOL - 4800000*decMul) {
            currentCommunityPool -= 1200000*decMul;
            amount += 1200000*decMul;
    }

    if (now >= TGE + 2*month && currentCommunityPool == COMMUNITY_POOL - 6000000*decMul) {
            currentCommunityPool -= 1200000*decMul;
            amount += 1200000*decMul;
    }

    if (now >= TGE + 3*month && currentCommunityPool == COMMUNITY_POOL - 7200000*decMul) {
            currentCommunityPool -= 1200000*decMul;
            amount += 1200000*decMul;
    }
    if (now >= TGE + 4*month && currentCommunityPool == COMMUNITY_POOL - 8400000*decMul) {
            currentCommunityPool -= 1200000*decMul;
            amount += 1200000*decMul;
    }
    if (now >= TGE + 5*month && currentCommunityPool == COMMUNITY_POOL - 9600000*decMul) {
            currentCommunityPool -= 1200000*decMul;
            amount += 1200000*decMul;
    }
    if (now >= TGE + 6*month && currentCommunityPool == COMMUNITY_POOL - 10800000*decMul) {
            currentCommunityPool -= 1200000*decMul;
            amount += 1200000*decMul;
    }
        
    // 25% each 6 months
    require(amount > 0, "nothing to claim");

    token.transfer(communityAddress, amount);
}

/**
 * @dev claim community tokens from the contract balance.
 * Can be used only by an owner or from communityAddress
 */