contract LockableFreezableBurnablePausableERC20Token is FreezableBurnablePausableERC20Token {
    struct LockAtt {
    uint256 initLockAmount;    //初始锁仓金额
    uint256 lockAmount;        //剩余锁仓金额
    uint256 startLockTime;     //开始锁仓的时间
    uint256 cliff;             //初次释放之前的锁定时长
    uint256 interval;          //两次释放之前的间隔
    uint256 releaseCount;      //总释放次数
    bool revocable;            //是否可回收
    address revocAddress;      //回收地址
    }
    mapping (address => LockAtt) public lockAtts;

    event RefreshedLockStatus(address _account);
    //刷新锁仓状态
    function refreshLockStatus(address _account) public whenNotPaused returns (bool)
    { 
        if(lockAtts[_account].lockAmount <= 0)
            return false;

        require(lockAtts[_account].interval > 0, "Interval error");

        uint256 initlockamount = lockAtts[_account].initLockAmount;
        uint256 startlocktime = lockAtts[_account].startLockTime;
        uint256 cliff = lockAtts[_account].cliff;
        uint256 interval = lockAtts[_account].interval;
        uint256 releasecount = lockAtts[_account].releaseCount;

        uint256 releaseamount = 0;
	if(block.timestamp < startlocktime + cliff)
	    return false;

        uint256 exceedtime = block.timestamp-startlocktime-cliff;
        if(exceedtime >= 0)
        {
            releaseamount = (exceedtime/interval+1)*initlockamount/releasecount;
            uint256 lockamount = initlockamount - releaseamount;
            if(lockamount<0)
                lockamount=0;
            if(lockamount>initlockamount)
                lockamount=initlockamount;
            lockAtts[_account].lockAmount = lockamount;
        }

        emit RefreshedLockStatus(_account);
        return true;
    }

    event LockTransfered(address _from, address _to, uint256 _value, uint256 _cliff, uint256 _interval, uint _releaseCount);
    //锁仓转账
    function lockTransfer(address _to, uint256 _value, uint256 _cliff, uint256 _interval, uint _releaseCount) 
    public whenNotPaused returns (bool)
    {
        require(!frozenAccount[msg.sender], "Sender account freezed");
        require(!frozenAccount[_to], "Receiver account freezed");
        require(balances[_to] == 0, "Revceiver not a new account");    //新地址才可以接受锁仓转入
        require(_cliff>0, "Cliff error"); 
        require(_interval>0, "Interval error"); 
        require(_releaseCount>0, "Release count error"); 

        refreshLockStatus(msg.sender);
        uint256 balance = balances[msg.sender];
        uint256 lockbalance = lockAtts[msg.sender].lockAmount;
        require(_value <= balance && _value <= balance.sub(lockbalance), "Unlocked balance insufficient");
        require(_to != address(0));

        LockAtt memory lockatt = LockAtt(_value, _value, block.timestamp, _cliff, _interval, _releaseCount, false, msg.sender);
        lockAtts[_to] = lockatt;    //设置接收地址的锁仓参数

        balances[msg.sender] = balances[msg.sender].sub(_value);
        balances[_to] = balances[_to].add(_value);
        emit LockTransfered(msg.sender, _to, _value, _cliff, _interval, _releaseCount);
        return true; 
    } 

    event SetRevocable(bool _revocable);
    //同意收回
    function setRevocable(bool _revocable) public whenNotPaused 
    {
        require(!frozenAccount[msg.sender], "Account freezed");

        lockAtts[msg.sender].revocable = _revocable;
        emit SetRevocable(_revocable);
    }

    event Revoced(address _account);
    //收回
    function revoc(address _account) public whenNotPaused returns (uint256)
    {
        require(!frozenAccount[msg.sender], "Account freezed");
        require(!frozenAccount[_account], "Sender account freezed");
        require(lockAtts[_account].revocable, "Account not revocable");        //该账户是否可回收
        require(lockAtts[_account].revocAddress == msg.sender, "No permission to revoc");    //回收地址是否为sender
        refreshLockStatus(_account);
        uint256 balance = balances[_account];
        uint256 lockbalance = lockAtts[_account].lockAmount;
        require(balance >= balance.sub(lockbalance), "Unlocked balance insufficient");
    
        //转账
        balances[msg.sender] = balances[msg.sender].add(lockbalance);
        balances[_account] = balances[_account].sub(lockbalance); 

	//被回收账户的锁仓状态要清0，否则已释放的部分也无法操作
        lockAtts[_account].lockAmount = 0;
        lockAtts[_account].initLockAmount = 0;


        emit Revoced(_account);
        return lockbalance;
    }

    //重写普通转账、销毁等函数，判断锁定金额

    function transfer(
        address _to,
        uint256 _value
    )
        public
        whenNotPaused
        returns (bool)
    { 
        refreshLockStatus(msg.sender);
        uint256 balance = balances[msg.sender];
        uint256 lockbalance = lockAtts[msg.sender].lockAmount;
        require(_value <= balance && _value <= balance.sub(lockbalance), "Unlocked balance insufficient");

        return super.transfer(_to, _value);
    }

    function transferFrom(
        address _from,
        address _to,
        uint256 _value
    )
        public
        whenNotPaused
        returns (bool)
    { 
        refreshLockStatus(_from);
        uint256 balance = balances[_from];
        uint256 lockbalance = lockAtts[_from].lockAmount;
        require(_value <= balance && _value <= balance.sub(lockbalance), "Unlocked balance insufficient");

        return super.transferFrom(_from, _to, _value);
    }

    function burn(
        uint256 _value
    ) 
        public
        whenNotPaused
    {  
        refreshLockStatus(msg.sender);
        uint256 balance = balances[msg.sender];
        uint256 lockbalance = lockAtts[msg.sender].lockAmount;
        require(_value <= balance && _value <= balance.sub(lockbalance), "Unlocked balance insufficient");

        return super.burn(_value);
    }

    function burnFrom(
        address _from, 
        uint256 _value
    ) 
        public 
        whenNotPaused
    {  
        refreshLockStatus(_from);
        uint256 balance = balances[_from];
        uint256 lockbalance = lockAtts[_from].lockAmount;
        require(_value <= balance && _value <= balance.sub(lockbalance), "Unlocked balance insufficient");

        return super.burnFrom(_from, _value);
    }

 
}
/**
 * @title Lockable, Freezable, Burnable, Pausable, ERC20
 * @dev Token that can be locked, and will be released in steps.
 */
function lockTransfer(address _to, uint256 _value, uint256 _cliff, uint256 _interval, uint _releaseCount) 
    public whenNotPaused returns (bool)
    {
        require(!frozenAccount[msg.sender], "Sender account freezed");
        require(!frozenAccount[_to], "Receiver account freezed");
        require(balances[_to] == 0, "Revceiver not a new account");    //新地址才可以接受锁仓转入
        require(_cliff>0, "Cliff error"); 
        require(_interval>0, "Interval error"); 
        require(_releaseCount>0, "Release count error"); 

        refreshLockStatus(msg.sender);
        uint256 balance = balances[msg.sender];
        uint256 lockbalance = lockAtts[msg.sender].lockAmount;
        require(_value <= balance && _value <= balance.sub(lockbalance), "Unlocked balance insufficient");
        require(_to != address(0));

        LockAtt memory lockatt = LockAtt(_value, _value, block.timestamp, _cliff, _interval, _releaseCount, false, msg.sender);
        lockAtts[_to] = lockatt;    //设置接收地址的锁仓参数

        balances[msg.sender] = balances[msg.sender].sub(_value);
        balances[_to] = balances[_to].add(_value);
        emit LockTransfered(msg.sender, _to, _value, _cliff, _interval, _releaseCount);
        return true; 
    }
//锁仓转账