contract overflow is ERC20Detailed, ERC20Pausable, ERC20Capped, ERC20Burnable {

    // The total amount of locks at the specified address.
    mapping (address => uint256) public totalLockAmount;
    // The amount of released addresses of the specified address.
    mapping (address => uint256) public releasedAmount;

    mapping (address => uint256) public lockedAmount;

    mapping (address => allocation[]) public allocations;

    struct allocation {
        uint256 releaseTime;
        uint256 releaseAmount;
    }

    event LockToken(address indexed beneficiary, uint256[] releaseAmounts, uint256[] releaseTimes);
    event ReleaseToken(address indexed user, uint256 releaseAmount, uint256 releaseTime);

    /**
     *  Initialize token basic information.
     */
    constructor(string memory token_name, string memory token_symbol, uint8 token_decimals, uint256 token_cap) public
        ERC20Detailed(token_name, token_symbol, token_decimals) {
        _cap = token_cap * 10 ** uint256(token_decimals);
        
    }

    /**
     *  Send the token to the beneficiary and lock it, and the timestamp and quantity of locks can be set by owner.
     * @param _beneficiary A specified address.
     * @param _releaseTimes Array,the timesamp of release token.
     * @param _releaseAmounts Array,the amount of release token.
     */
    function lockToken(address _beneficiary, uint256[] memory _releaseTimes, uint256[] memory _releaseAmounts) public onlyOwner returns(bool) {
        require(_beneficiary != address(0), "Token: the target address cannot be a zero address");
        require(_releaseTimes.length == _releaseAmounts.length, "Token: the array length must be equal");
        uint256 _lockedAmount;
        for (uint256 i = 0; i < _releaseTimes.length; i++) {
            _lockedAmount = _lockedAmount.add(_releaseAmounts[i]);
            require(_releaseAmounts[i] > 0, "Token: the amount must be greater than 0");
            require(_releaseTimes[i] >= now, "Token: the time must be greater than current time");
            //Save the locktoken information
            allocations[_beneficiary].push(allocation(_releaseTimes[i], _releaseAmounts[i]));
        }
        lockedAmount[_beneficiary] = lockedAmount[_beneficiary].add(_lockedAmount);
        totalLockAmount[_beneficiary] = totalLockAmount[_beneficiary].add(_lockedAmount);
        _balances[owner] = _balances[owner].sub(_lockedAmount); //Remove this part of the locked token from the owner.
        _balances[_beneficiary] = _balances[_beneficiary].add(_lockedAmount);
        emit Transfer(owner, _beneficiary, _lockedAmount);
        emit LockToken(_beneficiary, _releaseAmounts, _releaseTimes);
        return true;
    }

    /**
     * Rewrite the transfer function to automatically unlock the locked token.
     */
    function transfer(address to, uint256 value) public returns (bool) {
        if(releasableAmount(msg.sender) > 0) {
            _releaseToken(msg.sender);
        }

        require(_balances[msg.sender].sub(lockedAmount[msg.sender]) >= value, "Token: not enough token balance");
        super.transfer(to, value);
        return true;
    }

    /**
     *  Rewrite the transferFrom function to automatically unlock the locked token.
     */
    function transferFrom(address from, address to, uint256 value) public returns (bool) {
        if(releasableAmount(from) > 0) {
            _releaseToken(from);
        }
        require(_balances[from].sub(lockedAmount[from]) >= value, "Token: not enough token balance");
        super.transferFrom(from, to, value);
        return true;
    }

    /**
     *  Get the amount of current timestamps that can be released.
     * @param addr A specified address.
     */
    function releasableAmount(address addr) public view returns(uint256) {
        uint256 num = 0;
        for (uint256 i = 0; i < allocations[addr].length; i++) {
            if (now >= allocations[addr][i].releaseTime) {
                num = num.add(allocations[addr][i].releaseAmount);
            }
        }
        return num.sub(releasedAmount[addr]);
    }

    /**
     * Internal function, implement the basic functions of releasing tokens.
     */
    function _releaseToken(address _owner) internal returns(bool) {
        
        //Get the amount of release and update the lock-plans data.
        uint256 amount = releasableAmount(_owner);
        require(amount > 0, "Token: no releasable tokens");
        lockedAmount[_owner] = lockedAmount[_owner].sub(amount);
        releasedAmount[_owner] = releasedAmount[_owner].add(amount);
        // If the token on this address has been completely released, the address lock record and the total amount of locks and the released amount are cleared.
        if (releasedAmount[_owner] == totalLockAmount[_owner]) {
            delete allocations[_owner]; // Clear the address history data.
            totalLockAmount[_owner] = 0;
            releasedAmount[_owner] = 0;
            lockedAmount[_owner] = 0;
        }
        emit ReleaseToken(_owner, amount, now);
        return true;
    }

}
/**
 *  Implementation of the TigerCash.
 */
function releasableAmount(address addr) public view returns(uint256) {
    uint256 num = 0;
    for (uint256 i = 0; i < allocations[addr].length; i++) {
        if (now >= allocations[addr][i].releaseTime) {
            num = num.add(allocations[addr][i].releaseAmount);
        }
    }
    return num.sub(releasedAmount[addr]);
}

/**
 *  Get the amount of current timestamps that can be released.
 * @param addr A specified address.
 */