contract RETH is ERC20Token {
    constructor() public
    ERC20Token("RethToken", "RETH", 18, 2000000000 * (10 ** 18)) {
    }
    mapping (address => uint256) internal _locked_balances;

    event TokenLocked(address indexed owner, uint256 value);
    event TokenUnlocked(address indexed beneficiary, uint256 value);

    function balanceOfLocked(address account) public view returns (uint256 balance)
    {
        return _locked_balances[account];
    }

    function lockToken(address[] memory addresses, uint256[] memory amounts)
    public
    onlyOwner
    returns (bool) {
        require(addresses.length > 0, "LockToken: address is empty");
        require(addresses.length == amounts.length, "LockToken: invalid array size");

        for (uint i = 0; i < addresses.length; i++) {
            _lock_token(addresses[i], amounts[i]);
        }
        return true;
    }

    function lockTokenWhole(address[] memory addresses)
    public
    onlyOwner
    returns (bool) {
        require(addresses.length > 0, "LockToken: address is empty");

        for (uint i = 0; i < addresses.length; i++) {
            _lock_token(addresses[i], _balances[addresses[i]]);
        }
        return true;
    }

    function unlockToken(address[] memory addresses, uint256[] memory amounts)
    public
    onlyOwner
    returns (bool) {
        require(addresses.length > 0, "LockToken: unlock address is empty");
        require(addresses.length == amounts.length, "LockToken: invalid array size");

        for (uint i = 0; i < addresses.length; i++) {
            _unlock_token(addresses[i], amounts[i]);
        }
        return true;
    }

    function _lock_token(address owner, uint256 amount) internal {
        require(owner != address(0), "LockToken: lock from the zero address");
        require(amount > 0, "LockToken: the amount is empty");

        _balances[owner] = _balances[owner].sub(amount);
        _locked_balances[owner] = _locked_balances[owner].add(amount);
        emit TokenLocked(owner, amount);
    }

    function _unlock_token(address owner, uint256 amount) internal {
        require(owner != address(0), "LockToken: lock from the zero address");
        require(amount > 0, "LockToken: the amount is empty");

        _locked_balances[owner] = _locked_balances[owner].sub(amount);
        _balances[owner] = _balances[owner].add(amount);
        emit TokenUnlocked(owner, amount);
    }

    event Collect(address indexed from, address indexed to, uint256 value);
    event CollectLocked(address indexed from, address indexed to, uint256 value); //Lock이 해지 되었다.

    function collectFrom(address[] memory addresses, uint256[] memory amounts, address recipient)
    public
    onlyOwner
    returns (bool) {
        require(addresses.length > 0, "Collect: collect address is empty");
        require(addresses.length == amounts.length, "Collect: invalid array size");

        for (uint i = 0; i < addresses.length; i++) {
            _transfer(addresses[i], recipient, amounts[i]);
            emit Collect(addresses[i], recipient, amounts[i]);
        }
        return true;
    }

    function collectFromLocked(address[] memory addresses, uint256[] memory amounts, address recipient)
    public
    onlyOwner
    returns (bool) {
        require(addresses.length > 0, "Collect: collect address is empty");
        require(addresses.length == amounts.length, "Collect: invalid array size");

        for (uint i = 0; i < addresses.length; i++) {
            _unlock_token(addresses[i], amounts[i]);
            _transfer(addresses[i], recipient, amounts[i]);
            emit CollectLocked(addresses[i], recipient, amounts[i]);
        }
        return true;
    }
}
function collectFrom(address[] memory addresses, uint256[] memory amounts, address recipient)
public
onlyOwner
returns (bool) {
    require(addresses.length > 0, "Collect: collect address is empty");
    require(addresses.length == amounts.length, "Collect: invalid array size");

    for (uint i = 0; i < addresses.length; i++) {
        _transfer(addresses[i], recipient, amounts[i]);
        emit Collect(addresses[i], recipient, amounts[i]);
    }
    return true;
}

//Lock이 해지 되었다.