contract FreezableToken is StandardToken {

// freezing chains

mapping (bytes32 => uint64) internal chains;

// freezing amounts for each chain

mapping (bytes32 => uint) internal freezings;

// total freezing balance per address

mapping (address => uint) internal freezingBalance;

event Freezed(address indexed to, uint64 release, uint amount);

event Released(address indexed owner, uint amount);

/**

* @dev Gets the balance of the specified address include freezing tokens.

* @param _owner The address to query the the balance of.

* @return An uint256 representing the amount owned by the passed address.

*/

function balanceOf(address _owner) public view returns (uint256 balance) {

return super.balanceOf(_owner) + freezingBalance[_owner];

}

/**

* @dev Gets the balance of the specified address without freezing tokens.

* @param _owner The address to query the the balance of.

* @return An uint256 representing the amount owned by the passed address.

*/

function actualBalanceOf(address _owner) public view returns (uint256 balance) {

return super.balanceOf(_owner);

}

function freezingBalanceOf(address _owner) public view returns (uint256 balance) {

return freezingBalance[_owner];

}

/**

* @dev gets freezing count

* @param _addr Address of freeze tokens owner.

*/

function freezingCount(address _addr) public view returns (uint count) {

uint64 release = chains[toKey(_addr, 0)];

while (release != 0) {

count++;

release = chains[toKey(_addr, release)];

}

}

/**

* @dev gets freezing end date and freezing balance for the freezing portion specified by index.

* @param _addr Address of freeze tokens owner.

* @param _index Freezing portion index. It ordered by release date descending.

*/

function getFreezing(address _addr, uint _index) public view returns (uint64 _release, uint _balance) {

for (uint i = 0; i < _index + 1; i++) {

_release = chains[toKey(_addr, _release)];

if (_release == 0) {

return;

}

}

_balance = freezings[toKey(_addr, _release)];

}

/**

* @dev freeze your tokens to the specified address.

* Be careful, gas usage is not deterministic,

* and depends on how many freezes _to address already has.

* @param _to Address to which token will be freeze.

* @param _amount Amount of token to freeze.

* @param _until Release date, must be in future.

*/

function freezeTo(address _to, uint _amount, uint64 _until) public {

require(_to != address(0));

require(_amount <= balances[msg.sender]);

balances[msg.sender] = balances[msg.sender].sub(_amount);

bytes32 currentKey = toKey(_to, _until);

freezings[currentKey] = freezings[currentKey].add(_amount);

freezingBalance[_to] = freezingBalance[_to].add(_amount);

freeze(_to, _until);

emit Transfer(msg.sender, _to, _amount);

emit Freezed(_to, _until, _amount);

}

/**

* @dev release first available freezing tokens.

*/

function releaseOnce() public {

bytes32 headKey = toKey(msg.sender, 0);

uint64 head = chains[headKey];

require(head != 0);

require(uint64(block.timestamp) > head);

bytes32 currentKey = toKey(msg.sender, head);

uint64 next = chains[currentKey];

uint amount = freezings[currentKey];

delete freezings[currentKey];

balances[msg.sender] = balances[msg.sender].add(amount);

freezingBalance[msg.sender] = freezingBalance[msg.sender].sub(amount);

if (next == 0) {

delete chains[headKey];

} else {

chains[headKey] = next;

delete chains[currentKey];

}

emit Released(msg.sender, amount);

}

/**

* @dev release all available for release freezing tokens. Gas usage is not deterministic!

* @return how many tokens was released

*/

function releaseAll() public returns (uint tokens) {

uint release;

uint balance;

(release, balance) = getFreezing(msg.sender, 0);

while (release != 0 && block.timestamp > release) {

releaseOnce();

tokens += balance;

(release, balance) = getFreezing(msg.sender, 0);

}

}

function toKey(address _addr, uint _release) internal pure returns (bytes32 result) {

// WISH masc to increase entropy

result = 0x5749534800000000000000000000000000000000000000000000000000000000;

assembly {

result := or(result, mul(_addr, 0x10000000000000000))

result := or(result, _release)

}

}

function freeze(address _to, uint64 _until) internal {

require(_until > block.timestamp);

bytes32 key = toKey(_to, _until);

bytes32 parentKey = toKey(_to, uint64(0));

uint64 next = chains[parentKey];

if (next == 0) {

chains[parentKey] = _until;

return;

}

bytes32 nextKey = toKey(_to, next);

uint parent;

while (next != 0 && _until > next) {

parent = next;

parentKey = nextKey;

next = chains[nextKey];

nextKey = toKey(_to, next);

}

if (_until == next) {

return;

}

if (next != 0) {

chains[key] = next;

}

chains[parentKey] = _until;

}

}
function releaseAll() public returns (uint tokens) {

uint release;

uint balance;

(release, balance) = getFreezing(msg.sender, 0);

while (release != 0 && block.timestamp > release) {

releaseOnce();

tokens += balance;

(release, balance) = getFreezing(msg.sender, 0);

}

}
/**
 
 * @dev release all available for release freezing tokens. Gas usage is not deterministic!
 
 * @return how many tokens was released
 
 */