def METHOD_NAME(self, ip: IPAddress, state: IPState) -> IPDesc:
    """ Remove, mark, add: move IP to a new state """
    assert state in IPState, "unknown state %s" % state
    old_state = self.get_ip_state(ip)
    ip_desc = self.ip_states[old_state][ip.exploded]
    # some internal checks
    assert ip_desc.state != state, \
        "move IP to the same state %s" % state
    assert ip == ip_desc.ip, "Unmatching ip_desc for %s" % ip
    if ip_desc.state == IPState.FREE:
        assert ip_desc.sid is None, \
            "Unexpected sid in a freed IPDesc {}".format(ip_desc)
    else:
        assert ip_desc.sid is not None, \
            "Missing sid in state %s IPDesc {}".format(ip_desc)
    # remove, mark, add
    self.remove_ip_from_state(ip, old_state)
    ip_desc.state = state
    self.add_ip_to_state(ip, ip_desc, state)
    return ip_desc